Skip to content

Commit

Permalink
fix issue 2356 (#2428)
Browse files Browse the repository at this point in the history
  • Loading branch information
gqcn authored Feb 8, 2023
1 parent 3adae3a commit 4a66301
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
26 changes: 25 additions & 1 deletion contrib/drivers/mysql/mysql_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ func Test_Issue2231(t *testing.T) {
link := `mysql:root:12345678@tcp(127.0.0.1:3306)/a正bc式?loc=Local&parseTime=true`

gtest.C(t, func(t *gtest.T) {

match, err := gregex.MatchString(linkPattern, link)
t.AssertNil(err)
t.Assert(match[1], "mysql")
Expand All @@ -476,3 +475,28 @@ func Test_Issue2231(t *testing.T) {
t.Assert(match[7], "loc=Local&parseTime=true")
})
}

// https://github.com/gogf/gf/issues/2356
func Test_Issue2356(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
table := "demo_" + guid.S()
if _, err := db.Exec(ctx, fmt.Sprintf(`
CREATE TABLE %s (
id BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`, table,
)); err != nil {
t.AssertNil(err)
}
defer dropTable(table)

if _, err := db.Exec(ctx, fmt.Sprintf(`INSERT INTO %s (id) VALUES (18446744073709551615);`, table)); err != nil {
t.AssertNil(err)
}

one, err := db.Model(table).One()
t.AssertNil(err)
t.AssertEQ(one["id"].Val(), uint64(18446744073709551615))
})
}
45 changes: 29 additions & 16 deletions database/gdb/gdb_core_underlying.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ package gdb
import (
"context"
"database/sql"

"github.com/gogf/gf/v2/util/gconv"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
"reflect"

"github.com/gogf/gf/v2"
"github.com/gogf/gf/v2/container/gvar"
Expand Down Expand Up @@ -364,26 +365,18 @@ func (c *Core) RowsToResult(ctx context.Context, rows *sql.Rows) (Result, error)
return nil, nil
}
// Column names and types.
columns, err := rows.ColumnTypes()
columnTypes, err := rows.ColumnTypes()
if err != nil {
return nil, err
}

var (
columnTypes = make([]string, len(columns))
columnNames = make([]string, len(columns))
)
for k, v := range columns {
columnTypes[k] = v.DatabaseTypeName()
columnNames[k] = v.Name()
}
if len(columnNames) > 0 {
if len(columnTypes) > 0 {
if internalData := c.GetInternalCtxDataFromCtx(ctx); internalData != nil {
internalData.FirstResultColumn = columnNames[0]
internalData.FirstResultColumn = columnTypes[0].Name()
}
}
var (
values = make([]interface{}, len(columnNames))
values = make([]interface{}, len(columnTypes))
result = make(Result, 0)
scanArgs = make([]interface{}, len(values))
)
Expand All @@ -399,13 +392,13 @@ func (c *Core) RowsToResult(ctx context.Context, rows *sql.Rows) (Result, error)
if value == nil {
// DO NOT use `gvar.New(nil)` here as it creates an initialized object
// which will cause struct converting issue.
record[columnNames[i]] = nil
record[columnTypes[i].Name()] = nil
} else {
var convertedValue interface{}
if convertedValue, err = c.db.ConvertValueForLocal(ctx, columnTypes[i], value); err != nil {
if convertedValue, err = c.columnValueToLocalValue(ctx, value, columnTypes[i]); err != nil {
return nil, err
}
record[columnNames[i]] = gvar.New(convertedValue)
record[columnTypes[i].Name()] = gvar.New(convertedValue)
}
}
result = append(result, record)
Expand All @@ -415,3 +408,23 @@ func (c *Core) RowsToResult(ctx context.Context, rows *sql.Rows) (Result, error)
}
return result, nil
}

func (c *Core) columnValueToLocalValue(ctx context.Context, value interface{}, columnType *sql.ColumnType) (interface{}, error) {
var scanType = columnType.ScanType()
if scanType != nil {
// Common basic builtin types.
switch scanType.Kind() {
case
reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
return gconv.Convert(
gconv.String(value),
columnType.ScanType().String(),
), nil
}
}
// Other complex types, especially custom types.
return c.db.ConvertValueForLocal(ctx, columnType.DatabaseTypeName(), value)
}
2 changes: 1 addition & 1 deletion util/gconv/gconv_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ func bindVarToStructAttr(structReflectValue reflect.Value, attrName string, valu
}

// bindVarToReflectValueWithInterfaceCheck does bind using common interfaces checks.
func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value interface{}) (err error, ok bool) {
func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value interface{}) (error, bool) {
var pointer interface{}
if reflectValue.Kind() != reflect.Ptr && reflectValue.CanAddr() {
reflectValueAddr := reflectValue.Addr()
Expand Down

0 comments on commit 4a66301

Please sign in to comment.