## Summary
- Fix nested map conversion data loss when using `gconv.Scan()` or
`MapToMap()`
- When converting `map[string]any` to `map[string]map[string]float64`,
the nested data was lost
- Root cause: `MapToMap` incorrectly called `Struct()` for map value
types
- Solution: Separate `reflect.Map` handling from `reflect.Struct`, use
recursive `MapToMap()` for nested maps
## Test plan
- [x] Added test case reproducing original bug (nested map conversion)
- [x] Added test cases for deep nesting (3-5 levels)
- [x] Added test case for different key types
- [x] Added test case for empty nested map
- [x] Verified struct conversion still works (no regression)
- [x] Verified no infinite recursion with timeout tests
- [x] All gconv tests pass
Closes#4542
---------
Co-authored-by: hailaz <739476267@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
The gconv.UnsafeStrToBytes function has been updated to use the Go 1.20+
safe approach, as the previous implementation could cause a panic in
certain scenarios.
For example, when an HTTP request header specifies Content-Type:
application/x-www-form-urlencoded, but the actual request body contains
JSON data, the following code attempts to detect and handle this case:
```go
if !gregex.IsMatchString(`^[\w\-\[\]]+$`, name) && len(r.PostForm) == 1 {
// It might be JSON/XML content.
if s := gstr.Trim(name + strings.Join(values, " ")); len(s) > 0 {
if s[0] == '{' && s[len(s)-1] == '}' || s[0] == '<' && s[len(s)-1] == '>' {
r.bodyContent = gconv.UnsafeStrToBytes(s)
params = ""
break
}
}
}
```
However, after this assignment, bodyContent ends up with a capacity
(cap) of 0. slice operations like [:] perform stricter validation and
will panic if the capacity is 0. This causes a panic in functions such
as:
```go
body = bytes.TrimSpace(body)
func TrimSpace(s []byte) []byte {
...
return s[start:stop] // panic here due to cap == 0
}
```
The capacity (cap) of the slice returned by directly calling this
function is unpredictable, as it depends on the adjacent memory layout.
However, within the framework, this causes issues—likely because,
starting from Go 1.22, the standard library's parseForm implementation
consistently appends a trailing zero byte after the string data in
memory.
This PR fix the problem.
------------------------------------
gconv unsafe str to bytes 改用 go1.20 后的写法,之前的写法在某些场景下会 panic
例如 http 请求头为`application/x-www-form-urlencoded`,实际的 body 为 json,
经过解析后
```go
if !gregex.IsMatchString(`^[\w\-\[\]]+$`, name) && len(r.PostForm) == 1 {
// It might be JSON/XML content.
if s := gstr.Trim(name + strings.Join(values, " ")); len(s) > 0 {
if s[0] == '{' && s[len(s)-1] == '}' || s[0] == '<' && s[len(s)-1] == '>' {
r.bodyContent = gconv.UnsafeStrToBytes(s)
params = ""
break
}
}
}
```
bodyContent的 cap 为 0,由于切片操作[:]会校验 cap 为 0,会直接 panic
```go
body = bytes.TrimSpace(body)
---
func TrimSpace(s []byte) []byte {
...
return s[start:stop] // panic
}
```
直接使用这个函数得到的 cap 会是随机的, 因为跟的内存不确定,但是在框架中有问题,估计是1.22 后标准库parseForm
的时候后面内存固定跟了个 0
该 PR 修复这个问题
Co-authored-by: liov-ola <liov@olaparty.sg>
This pull request significantly improves PostgreSQL array type handling
and conversion in the `pgsql` driver, providing more accurate type
mapping and conversion logic, especially for array types. It introduces
comprehensive documentation, refactors conversion logic to use the `pq`
package for array types, and adds extensive unit tests to ensure
correctness and error handling. Additionally, minor enhancements and
clarifications are made to upsert formatting and table field queries.
### PostgreSQL Array Type Handling and Conversion
* Refactored `CheckLocalTypeForField` and `ConvertValueForLocal` methods
in `contrib/drivers/pgsql/pgsql_convert.go` to accurately map PostgreSQL
array types (such as `_int2`, `_int4`, `_int8`, `_float4`, `_float8`,
`_bool`, `_varchar`, `_text`, `_char`, `_bpchar`, `_numeric`,
`_decimal`, `_money`, `_bytea`) to their corresponding Go types, using
the `pq` package for conversion. Added detailed documentation and
mapping tables for supported types.
[[1]](diffhunk://#diff-a3b1e68bfa29fbcfda7c703bbe875fa82e958f6c3ad942ef82193a9dd8ad67e2R46-R63)
[[2]](diffhunk://#diff-a3b1e68bfa29fbcfda7c703bbe875fa82e958f6c3ad942ef82193a9dd8ad67e2L56-R103)
[[3]](diffhunk://#diff-a3b1e68bfa29fbcfda7c703bbe875fa82e958f6c3ad942ef82193a9dd8ad67e2R112-R209)
* Added comprehensive unit tests in
`contrib/drivers/pgsql/pgsql_z_unit_convert_test.go` to verify type
mapping and conversion for all supported array types, including error
cases for invalid input.
### Utility and API Improvements
* Added a new `Bools()` method to the `gvar.Var` type in
`container/gvar/gvar_slice.go` for converting values to `[]bool`, with
corresponding unit tests in `container/gvar/gvar_z_unit_slice_test.go`.
[[1]](diffhunk://#diff-32e887e540e0170f785508d105cb794e4d54d854b53b6950973c80022973c490R11-R15)
[[2]](diffhunk://#diff-01453eca4d4b3e35d07ca105cb924c6441d0cd9df6cbcc337a89832c8d53057fR24-R41)
### SQL Formatting and Documentation
* Improved documentation and formatting in the upsert logic of
`contrib/drivers/pgsql/pgsql_format_upsert.go` to clarify the use of
`EXCLUDED` in PostgreSQL's `ON CONFLICT DO UPDATE`.
* Enhanced readability of the table field query in
`contrib/drivers/pgsql/pgsql_table_fields.go` by reformatting SQL and
clarifying field extraction.
---------
Co-authored-by: hailaz <739476267@qq.com>
Co-authored-by: houseme <housemecn@gmail.com>
fix: disable specific staticcheck rules and update lint config
- Disabled staticcheck rules SA1029, SA1019, S1000, and related checks
in `.golangci.yml` to filter out unwanted linter errors.
- Updated staticcheck checks list for more precise linting control.
- Clarified configuration for easier maintenance and future updates.
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: hailaz <739476267@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This pull request standardizes the use of the Go 1.18+ `any` type alias
instead of `interface{}` throughout the codebase. The change improves
code readability and aligns with modern Go best practices. The update
touches many files, including core data structures, code generation
templates, logging utilities, and test data, ensuring consistency across
all usages.
**Type alias migration to `any`:**
* Replaced all instances of `interface{}` with `any` in core data
structures such as `garray` and in generated model structs (e.g.,
`TableUser`, `User1`, `User2`) to modernize type usage.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[3]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[4]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[5]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[6]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
* Updated function signatures, method parameters, and return types from
`interface{}` to `any` in various parts of the codebase, including code
generation, service logic, and logging utilities (e.g., `mlog`).
[[1]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[2]](diffhunk://#diff-2b1953fb78cf3593d8c2c7d911e95b65fd0b847c30ed0b4d167d16fe6d781235L54-R74)
[[3]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[4]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
[[5]](diffhunk://#diff-c5d51d56f487779a2b6207c7ad26c7a20bbadcc846ce094fe60ab4cabff58c51L107-R107)
[[6]](diffhunk://#diff-f96e6a9fdb416eb1804ceaba1fe0ac637bff22c43837f8bb849c2366ce72d4a1L116-R121)
[[7]](diffhunk://#diff-f94c83a1b08ae060d9346f4a6031fc4a7b9a0b894e02d9afaa09018b6598eac0L112-R112)
[[8]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L36-R36)
[[9]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L74-R74)
[[10]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L96-R96)
**Generated code and templates:**
* Adjusted generated files and code generation templates to output `any`
instead of `interface{}` for relevant struct fields and function
signatures, ensuring that new code generation aligns with the updated
convention.
[[1]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[2]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[3]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[4]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[5]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
[[6]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[7]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[8]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
**Container and utility updates:**
* Refactored the `garray` container implementation and related
constructors/methods to use `[]any` instead of `[]interface{}`, along
with corresponding function signatures.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L52-R52)
[[3]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L62-R62)
[[4]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L73-R86)
[[5]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L96-R97)
[[6]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L107-R114)
[[7]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L124-R124)
[[8]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L135-R143)
[[9]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L167-R167)
These changes collectively modernize the codebase and prepare it for
future Go developments by using the idiomatic `any` type.
This PR includes the following changes:
- **Upgrade `.golangci.yml`**: Updated the configuration file to align
with the latest golangci-lint version, ensuring compatibility and
leveraging new features.
- **Refactor GitHub Action workflow**: Modified `golangci-lint.yml` in
the GitHub Actions workflow to reflect the updated configuration and
improve CI performance.
- **Codebase optimization**: Refactored code to address issues and
warnings raised by the updated golangci-lint rules, including:
- Improved function length and complexity.
- Enhanced error handling and variable naming conventions.
- Fixed minor issues such as unused imports and formatting
inconsistencies.
These changes aim to maintain code quality, ensure compatibility with
the latest tools, and improve overall maintainability.