diff --git a/core/convert_test.go b/core/convert_test.go index 38b6dbf..cd0818f 100644 --- a/core/convert_test.go +++ b/core/convert_test.go @@ -266,10 +266,16 @@ func TestConvert(t *testing.T) { if factory.Dialect() == dialects.Postgres { queryStr = "SELECT field0 FROM gobatis_convert2 WHERE id = $1" } - for _, test := range []interface{}{ + testcases := []interface{}{ "a", []byte{'a'}, - } { + } + if factory.Dialect() == dialects.DM { + testcases = []interface{}{ + "a", + } + } + for _, test := range testcases { id, err := convert.InsertStrNotNULL(test) if err != nil { t.Error(err) diff --git a/core/mapper.go b/core/mapper.go index b15d2a3..e34a34b 100644 --- a/core/mapper.go +++ b/core/mapper.go @@ -11,6 +11,7 @@ import ( "sync/atomic" "time" + "github.com/runner-mei/GoBatis/dialects" "github.com/runner-mei/GoBatis/reflectx" ) @@ -331,6 +332,27 @@ func (fi *FieldInfo) makeRValueForNumber(isPtr bool, isZero func(reflect.Value) } func (fi *FieldInfo) makeRValueForBytes(isPtr bool) func(dialect Dialect, param *Param, v reflect.Value) (interface{}, error) { + + doValuePtr := func(v interface{}) interface{} { + return v + } + doValue := func(v interface{}) interface{} { + return v + } + _, isStr := fi.Options["str"] + if isStr { + doValuePtr = func(v interface{}) interface{} { + // 达梦数库,无法正确处理 []byte 作为参数存入 varchar(x) 字段 + bs := v.(*[]byte) + return string(*bs) + } + doValue = func(v interface{}) interface{} { + // 达梦数库,无法正确处理 []byte 作为参数存入 varchar(x) 字段 + bs := v.([]byte) + return string(bs) + } + } + if _, ok := fi.Options["notnull"]; ok { return func(dialect Dialect, param *Param, v reflect.Value) (interface{}, error) { field := reflectx.FieldByIndexesReadOnly(v, fi.Index) @@ -341,12 +363,13 @@ func (fi *FieldInfo) makeRValueForBytes(isPtr bool) func(dialect Dialect, param if field.Elem().Len() == 0 { return nil, errors.New("field '" + fi.Field.Name + "' is empty value") } + return doValuePtr(field.Interface()), nil } else { if field.Len() == 0 { return nil, errors.New("field '" + fi.Field.Name + "' is empty value") } + return doValue(field.Interface()), nil } - return field.Interface(), nil } } @@ -360,17 +383,38 @@ func (fi *FieldInfo) makeRValueForBytes(isPtr bool) func(dialect Dialect, param if field.Elem().Len() == 0 { return nil, nil } + return doValuePtr(field.Interface()), nil } else { if field.Len() == 0 { return nil, nil } + return doValue(field.Interface()), nil } - return field.Interface(), nil } } return func(dialect Dialect, param *Param, v reflect.Value) (interface{}, error) { field := reflectx.FieldByIndexesReadOnly(v, fi.Index) - return field.Interface(), nil + if field.IsNil() { + return nil, nil + } + if !isStr { + return field.Interface(), nil + } + + if isPtr { + if field.Elem().IsNil() { + return nil, nil + } + if field.Elem().Len() == 0 { + return "", nil + } + return doValuePtr(field.Interface()), nil + } else { + if field.Len() == 0 { + return "", nil + } + return doValue(field.Interface()), nil + } } } @@ -592,7 +636,12 @@ func (fi *FieldInfo) makeRValueForAny(kind reflect.Kind, canNil bool) func(diale if err != nil { return nil, fmt.Errorf("field '%s' convert to json, %s", fi.Field.Name, err) } - return string(bs), nil + + if dialect == dialects.DM { + // 达梦数库,无法正确处理 []byte 作为参数存入 varchar(x) 字段 + return string(bs), nil + } + return bs, nil } } @@ -611,7 +660,12 @@ func (fi *FieldInfo) makeRValueForAny(kind reflect.Kind, canNil bool) func(diale if err != nil { return nil, fmt.Errorf("field '%s' convert to json, %s", fi.Field.Name, err) } - return string(bs), nil + + if dialect == dialects.DM { + // 达梦数库,无法正确处理 []byte 作为参数存入 varchar(x) 字段 + return string(bs), nil + } + return bs, nil } } @@ -1091,6 +1145,7 @@ var xormkeyTags = map[string]struct{}{ "int": {}, "integer": {}, "bigint": {}, + "str": {}, "char": {}, "varchar": {}, "tinytext": {}, diff --git a/core/session_test.go b/core/session_test.go index 0bbb311..b548b78 100644 --- a/core/session_test.go +++ b/core/session_test.go @@ -326,9 +326,8 @@ func TestSession(t *testing.T) { } for _, u := range users { - insertUser2.ID = u.ID - u.Birth = u.Birth.UTC() + // u.Birth = u.Birth.UTC() u.CreateTime = u.CreateTime.UTC() tests.AssertUser(t, insertUser2, u) diff --git a/tests/session.go b/tests/session.go index 1065e3e..2c391e3 100644 --- a/tests/session.go +++ b/tests/session.go @@ -1911,7 +1911,7 @@ var ( PostgreSQLOdbcUrl = "DSN=gobatis_test;uid=golang;pwd=123456" // + ";database=xxx" MySQLUrl = os.Getenv("mysql_username") + ":" + os.Getenv("mysql_password") + "@tcp(192.168.1.2:3306)/golang?autocommit=true&parseTime=true&multiStatements=true" MsSqlUrl = "sqlserver://golang:123456@127.0.0.1?database=golang&connection+timeout=30" - DMSqlUrl = "dm://" + os.Getenv("dm_username") + ":" + os.Getenv("dm_password") + "@" + os.Getenv("dm_host") + "?noConvertToHex=true" + DMSqlUrl = "dm://" + os.Getenv("dm_username") + ":" + os.Getenv("dm_password") + "@" + os.Getenv("dm_host") // + "?noConvertToHex=true" DmOdbcUrl = "DSN=" + os.Getenv("dm_odbc_name") + ";uid=" + os.Getenv("dm_odbc_username") + ";pwd=" + os.Getenv("dm_odbc_password") // + ";database=xxx" Db2Url = "HOSTNAME=127.0.0.1;DATABASE=golangtest;PORT=5000;UID=golangtest;PWD=golangtest" OracleUrl = "oracle://" + os.Getenv("oracle_username") + ":" + os.Getenv("oracle_password") + "@" + os.Getenv("oracle_host") + "/" + os.Getenv("oracle_service") diff --git a/tests/struct.go b/tests/struct.go index 002cfb6..6bd0352 100644 --- a/tests/struct.go +++ b/tests/struct.go @@ -7,6 +7,8 @@ import ( "net" "time" "unsafe" + + "github.com/runner-mei/GoBatis/dialects" ) type TestA1 struct { @@ -240,7 +242,13 @@ type DriverData1 struct { func (a DriverData1) Value() (driver.Value, error) { bs, err := json.Marshal(a) - return bs, err + if err != nil { + return nil, err + } + if TestDrv == dialects.DM.Name() { + return string(bs), nil + } + return bs, nil } var _ driver.Valuer = DriverData1{} @@ -251,7 +259,13 @@ type DriverData2 struct { func (a *DriverData2) Value() (driver.Value, error) { bs, err := json.Marshal(a) - return bs, err + if err != nil { + return nil, err + } + if TestDrv == dialects.DM.Name() { + return string(bs), nil + } + return bs, nil } var _ driver.Valuer = &DriverData2{} @@ -325,37 +339,37 @@ type TestE6 struct { type TestF1 struct { TableName struct{} `db:"gobatis_testf1"` ID int64 `db:"id,pk,autoincr"` - Field0 []byte `db:"field0"` + Field0 []byte `db:"field0,str"` } type TestF2 struct { TableName struct{} `db:"gobatis_testf1"` ID int64 `db:"id,pk,autoincr"` - Field0 *[]byte `db:"field0"` + Field0 *[]byte `db:"field0,str"` } type TestF3 struct { TableName struct{} `db:"gobatis_testf1"` ID int64 `db:"id,pk,autoincr"` - Field0 *[]byte `db:"field0,null"` + Field0 *[]byte `db:"field0,null,str"` } type TestF4 struct { TableName struct{} `db:"gobatis_testf1"` ID int64 `db:"id,pk,autoincr"` - Field0 []byte `db:"field0,null"` + Field0 []byte `db:"field0,null,str"` } type TestF5 struct { TableName struct{} `db:"gobatis_testf2"` ID int64 `db:"id,pk,autoincr"` - Field0 *[]byte `db:"field0,notnull"` + Field0 *[]byte `db:"field0,notnull,str"` } type TestF6 struct { TableName struct{} `db:"gobatis_testf2"` ID int64 `db:"id,pk,autoincr"` - Field0 []byte `db:"field0,notnull"` + Field0 []byte `db:"field0,notnull,str"` } type ConvertTestIntNull struct { diff --git a/tests/user.go b/tests/user.go index fa80a91..4fe0651 100644 --- a/tests/user.go +++ b/tests/user.go @@ -358,7 +358,7 @@ func AssertUser(t testing.TB, excepted, actual User) { t.Error("[ContactInfo] actual is", actual.ContactInfo) } - if excepted.Birth.Format("2006-01-02") != actual.Birth.Format("2006-01-02") { + if excepted.Birth.Format("2006-01-02") != actual.Birth.Local().Format("2006-01-02") { t.Error("[Birth] excepted is", excepted.Birth.Format("2006-01-02")) t.Error("[Birth] actual is", actual.Birth.Format("2006-01-02")) }