From 9e017d7e748c0c4a681c3ab63ad11e7619c46dfe Mon Sep 17 00:00:00 2001 From: "bing.ma" Date: Wed, 4 Jun 2025 14:36:24 +0800 Subject: [PATCH] support gaussdb --- tests/delete_test.go | 6 +- tests/error_translator_test.go | 4 +- tests/migrate_test.go | 367 ++++++++++++++++++++++++++++++- tests/multi_primary_keys_test.go | 9 +- tests/postgres_test.go | 8 +- tests/serializer_test.go | 2 +- tests/sql_builder_test.go | 2 +- tests/table_test.go | 77 +++++++ tests/tests_test.go | 11 + tests/update_test.go | 8 +- 10 files changed, 471 insertions(+), 23 deletions(-) diff --git a/tests/delete_test.go b/tests/delete_test.go index 5d112b4e..b9b5289c 100644 --- a/tests/delete_test.go +++ b/tests/delete_test.go @@ -206,9 +206,9 @@ func TestDeleteSliceWithAssociations(t *testing.T) { } } -// only sqlite, postgres, sqlserver support returning +// only sqlite, postgres, gaussdb, sqlserver support returning func TestSoftDeleteReturning(t *testing.T) { - if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlserver" { + if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlserver" { return } @@ -233,7 +233,7 @@ func TestSoftDeleteReturning(t *testing.T) { } func TestDeleteReturning(t *testing.T) { - if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlserver" { + if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlserver" { return } diff --git a/tests/error_translator_test.go b/tests/error_translator_test.go index ee54300e..765ea574 100644 --- a/tests/error_translator_test.go +++ b/tests/error_translator_test.go @@ -39,7 +39,7 @@ func TestSupportedDialectorWithErrDuplicatedKey(t *testing.T) { t.Fatalf("failed to connect database, got error %v", err) } - dialectors := map[string]bool{"sqlite": true, "postgres": true, "mysql": true, "sqlserver": true} + dialectors := map[string]bool{"sqlite": true, "postgres": true, "gaussdb": true, "mysql": true, "sqlserver": true} if supported, found := dialectors[db.Dialector.Name()]; !(found && supported) { return } @@ -81,7 +81,7 @@ func TestSupportedDialectorWithErrForeignKeyViolated(t *testing.T) { t.Fatalf("failed to connect database, got error %v", err) } - dialectors := map[string]bool{"sqlite": true, "postgres": true, "mysql": true, "sqlserver": true} + dialectors := map[string]bool{"sqlite": true, "postgres": true, "gaussdb": true, "mysql": true, "sqlserver": true} if supported, found := dialectors[db.Dialector.Name()]; !(found && supported) { return } diff --git a/tests/migrate_test.go b/tests/migrate_test.go index b60a6df5..1af6e10f 100644 --- a/tests/migrate_test.go +++ b/tests/migrate_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/moseszane168/gaussdb" "github.com/stretchr/testify/assert" "gorm.io/driver/postgres" @@ -83,7 +84,45 @@ func TestMigrate(t *testing.T) { } func TestAutoMigrateInt8PG(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { + return + } + + type Smallint int8 + + type MigrateInt struct { + Int8 Smallint + } + + tracer := Tracer{ + Logger: DB.Config.Logger, + Test: func(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { + sql, _ := fc() + if strings.HasPrefix(sql, "ALTER TABLE \"migrate_ints\" ALTER COLUMN \"int8\" TYPE smallint") { + t.Fatalf("shouldn't execute ALTER COLUMN TYPE if such type is already existed in DB schema: sql: %s", + sql) + } + }, + } + + DB.Migrator().DropTable(&MigrateInt{}) + + // The first AutoMigrate to make table with field with correct type + if err := DB.AutoMigrate(&MigrateInt{}); err != nil { + t.Fatalf("Failed to auto migrate: error: %v", err) + } + + // make new session to set custom logger tracer + session := DB.Session(&gorm.Session{Logger: tracer}) + + // The second AutoMigrate to catch an error + if err := session.AutoMigrate(&MigrateInt{}); err != nil { + t.Fatalf("Failed to auto migrate: error: %v", err) + } +} + +func TestAutoMigrateGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { return } @@ -182,7 +221,94 @@ func TestAutoMigrateNullable(t *testing.T) { } func TestSmartMigrateColumn(t *testing.T) { - fullSupported := map[string]bool{"mysql": true, "postgres": true}[DB.Dialector.Name()] + fullSupported := map[string]bool{"mysql": true, "postgres": true, "gaussdb": true}[DB.Dialector.Name()] + + type UserMigrateColumn struct { + ID uint + Name string + Salary float64 + Birthday time.Time `gorm:"precision:4"` + } + + DB.Migrator().DropTable(&UserMigrateColumn{}) + + DB.AutoMigrate(&UserMigrateColumn{}) + + type UserMigrateColumn2 struct { + ID uint + Name string `gorm:"size:128"` + Salary float64 `gorm:"precision:2"` + Birthday time.Time `gorm:"precision:2"` + NameIgnoreMigration string `gorm:"size:100"` + } + + if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn2{}); err != nil { + t.Fatalf("failed to auto migrate, got error: %v", err) + } + + columnTypes, err := DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn{}) + if err != nil { + t.Fatalf("failed to get column types, got error: %v", err) + } + + for _, columnType := range columnTypes { + switch columnType.Name() { + case "name": + if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 128 { + t.Fatalf("name's length should be 128, but got %v", length) + } + case "salary": + if precision, o, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 2 { + t.Fatalf("salary's precision should be 2, but got %v %v", precision, o) + } + case "birthday": + if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 2 { + t.Fatalf("birthday's precision should be 2, but got %v", precision) + } + } + } + + type UserMigrateColumn3 struct { + ID uint + Name string `gorm:"size:256"` + Salary float64 `gorm:"precision:3"` + Birthday time.Time `gorm:"precision:3"` + NameIgnoreMigration string `gorm:"size:128;-:migration"` + } + + if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn3{}); err != nil { + t.Fatalf("failed to auto migrate, got error: %v", err) + } + + columnTypes, err = DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn{}) + if err != nil { + t.Fatalf("failed to get column types, got error: %v", err) + } + + for _, columnType := range columnTypes { + switch columnType.Name() { + case "name": + if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 256 { + t.Fatalf("name's length should be 128, but got %v", length) + } + case "salary": + if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 3 { + t.Fatalf("salary's precision should be 2, but got %v", precision) + } + case "birthday": + if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 3 { + t.Fatalf("birthday's precision should be 2, but got %v", precision) + } + case "name_ignore_migration": + if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 100 { + t.Fatalf("name_ignore_migration's length should still be 100 but got %v", length) + } + } + } +} + +func TestSmartMigrateColumnGaussDB(t *testing.T) { + fullSupported := map[string]bool{"mysql": true, "gaussdb": true}[DB.Dialector.Name()] type UserMigrateColumn struct { ID uint @@ -850,7 +976,68 @@ func TestMigrateColumnOrder(t *testing.T) { // https://github.com/go-gorm/gorm/issues/5047 func TestMigrateSerialColumn(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { + return + } + + type Event struct { + ID uint `gorm:"primarykey"` + UID uint32 + } + + type Event1 struct { + ID uint `gorm:"primarykey"` + UID uint32 `gorm:"not null;autoIncrement"` + } + + type Event2 struct { + ID uint `gorm:"primarykey"` + UID uint16 `gorm:"not null;autoIncrement"` + } + + var err error + err = DB.Migrator().DropTable(&Event{}) + if err != nil { + t.Errorf("DropTable err:%v", err) + } + + // create sequence + err = DB.Table("events").AutoMigrate(&Event1{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + // delete sequence + err = DB.Table("events").AutoMigrate(&Event{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + // update sequence + err = DB.Table("events").AutoMigrate(&Event1{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + err = DB.Table("events").AutoMigrate(&Event2{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + DB.Table("events").Save(&Event2{}) + DB.Table("events").Save(&Event2{}) + DB.Table("events").Save(&Event2{}) + + events := make([]*Event, 0) + DB.Table("events").Find(&events) + + AssertEqual(t, 3, len(events)) + for _, v := range events { + AssertEqual(t, v.ID, v.UID) + } +} + +func TestMigrateSerialColumnGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { return } @@ -975,7 +1162,7 @@ func TestMigrateAutoIncrement(t *testing.T) { // https://github.com/go-gorm/gorm/issues/5320 func TestPrimarykeyID(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { return } @@ -1009,6 +1196,41 @@ func TestPrimarykeyID(t *testing.T) { } } +func TestPrimarykeyIDGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { + return + } + + type MissPKLanguage struct { + ID string `gorm:"type:uuid;default:uuid_generate_v4()"` + Name string + } + + type MissPKUser struct { + ID string `gorm:"type:uuid;default:uuid_generate_v4()"` + MissPKLanguages []MissPKLanguage `gorm:"many2many:miss_pk_user_languages;"` + } + + var err error + err = DB.Migrator().DropTable(&MissPKUser{}, &MissPKLanguage{}) + if err != nil { + t.Fatalf("DropTable err:%v", err) + } + // TODO: ERROR: could not open extension control file: No such file or directory (SQLSTATE 58P01) + DB.Exec(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp";`) + + err = DB.AutoMigrate(&MissPKUser{}, &MissPKLanguage{}) + if err != nil { + t.Fatalf("AutoMigrate err:%v", err) + } + + // patch + err = DB.AutoMigrate(&MissPKUser{}, &MissPKLanguage{}) + if err != nil { + t.Fatalf("AutoMigrate err:%v", err) + } +} + func TestCurrentTimestamp(t *testing.T) { if DB.Dialector.Name() != "mysql" { return @@ -1175,7 +1397,7 @@ func findColumnType(dest interface{}, columnName string) ( } func TestInvalidCachedPlanSimpleProtocol(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { return } @@ -1209,6 +1431,42 @@ func TestInvalidCachedPlanSimpleProtocol(t *testing.T) { } } +// TODO: ERROR: must have at least one column (SQLSTATE 0A000) +func TestInvalidCachedPlanSimpleProtocolGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { + return + } + + db, err := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{}) + if err != nil { + t.Errorf("Open err:%v", err) + } + + type Object1 struct{} + type Object2 struct { + Field1 string + } + type Object3 struct { + Field2 string + } + db.Migrator().DropTable("objects") + + err = db.Table("objects").AutoMigrate(&Object1{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + err = db.Table("objects").AutoMigrate(&Object2{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + err = db.Table("objects").AutoMigrate(&Object3{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } +} + func TestDifferentTypeWithoutDeclaredLength(t *testing.T) { type DiffType struct { ID uint @@ -1249,7 +1507,43 @@ func TestDifferentTypeWithoutDeclaredLength(t *testing.T) { } func TestMigrateArrayTypeModel(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { + return + } + + type ArrayTypeModel struct { + ID uint + Number string `gorm:"type:varchar(51);NOT NULL"` + TextArray []string `gorm:"type:text[];NOT NULL"` + NestedTextArray [][]string `gorm:"type:text[][]"` + NestedIntArray [][]int64 `gorm:"type:integer[3][3]"` + } + + var err error + DB.Migrator().DropTable(&ArrayTypeModel{}) + + err = DB.AutoMigrate(&ArrayTypeModel{}) + AssertEqual(t, nil, err) + + ct, err := findColumnType(&ArrayTypeModel{}, "number") + AssertEqual(t, nil, err) + AssertEqual(t, "varchar", ct.DatabaseTypeName()) + + ct, err = findColumnType(&ArrayTypeModel{}, "text_array") + AssertEqual(t, nil, err) + AssertEqual(t, "text[]", ct.DatabaseTypeName()) + + ct, err = findColumnType(&ArrayTypeModel{}, "nested_text_array") + AssertEqual(t, nil, err) + AssertEqual(t, "text[]", ct.DatabaseTypeName()) + + ct, err = findColumnType(&ArrayTypeModel{}, "nested_int_array") + AssertEqual(t, nil, err) + AssertEqual(t, "integer[]", ct.DatabaseTypeName()) +} + +func TestMigrateArrayTypeModelGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { return } @@ -1572,7 +1866,66 @@ func TestMigrateView(t *testing.T) { } func TestMigrateExistingBoolColumnPG(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { + return + } + + type ColumnStruct struct { + gorm.Model + Name string + StringBool string + SmallintBool int `gorm:"type:smallint"` + } + + type ColumnStruct2 struct { + gorm.Model + Name string + StringBool bool // change existing boolean column from string to boolean + SmallintBool bool // change existing boolean column from smallint or other to boolean + } + + DB.Migrator().DropTable(&ColumnStruct{}) + + if err := DB.AutoMigrate(&ColumnStruct{}); err != nil { + t.Errorf("Failed to migrate, got %v", err) + } + + if err := DB.Table("column_structs").AutoMigrate(&ColumnStruct2{}); err != nil { + t.Fatalf("no error should happened when auto migrate column, but got %v", err) + } + + if columnTypes, err := DB.Migrator().ColumnTypes(&ColumnStruct{}); err != nil { + t.Fatalf("no error should returns for ColumnTypes") + } else { + stmt := &gorm.Statement{DB: DB} + stmt.Parse(&ColumnStruct2{}) + + for _, columnType := range columnTypes { + switch columnType.Name() { + case "id": + if v, ok := columnType.PrimaryKey(); !ok || !v { + t.Fatalf("column id primary key should be correct, name: %v, column: %#v", columnType.Name(), + columnType) + } + case "string_bool": + dataType := DB.Dialector.DataTypeOf(stmt.Schema.LookUpField(columnType.Name())) + if !strings.Contains(strings.ToUpper(dataType), strings.ToUpper(columnType.DatabaseTypeName())) { + t.Fatalf("column name type should be correct, name: %v, length: %v, expects: %v, column: %#v", + columnType.Name(), columnType.DatabaseTypeName(), dataType, columnType) + } + case "smallint_bool": + dataType := DB.Dialector.DataTypeOf(stmt.Schema.LookUpField(columnType.Name())) + if !strings.Contains(strings.ToUpper(dataType), strings.ToUpper(columnType.DatabaseTypeName())) { + t.Fatalf("column name type should be correct, name: %v, length: %v, expects: %v, column: %#v", + columnType.Name(), columnType.DatabaseTypeName(), dataType, columnType) + } + } + } + } +} + +func TestMigrateExistingBoolColumnGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { return } diff --git a/tests/multi_primary_keys_test.go b/tests/multi_primary_keys_test.go index 4ecbff6a..28eb03f8 100644 --- a/tests/multi_primary_keys_test.go +++ b/tests/multi_primary_keys_test.go @@ -41,7 +41,7 @@ func TestManyToManyWithMultiPrimaryKeys(t *testing.T) { t.Skip("skip sqlite, sqlserver due to it doesn't support multiple primary keys with auto increment") } - if name := DB.Dialector.Name(); name == "postgres" || name == "mysql" { + if name := DB.Dialector.Name(); name == "postgres" || name == "mysql" || name == "gaussdb" { stmt := gorm.Statement{DB: DB} stmt.Parse(&Blog{}) stmt.Schema.LookUpField("ID").Unique = true @@ -142,6 +142,9 @@ func TestManyToManyWithCustomizedForeignKeys(t *testing.T) { if name := DB.Dialector.Name(); name == "postgres" { t.Skip("skip postgres due to it only allow unique constraint matching given keys") } + if name := DB.Dialector.Name(); name == "gaussdb" { + t.Skip("skip gaussdb due to it only allow unique constraint matching given keys") + } DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil { @@ -268,6 +271,10 @@ func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) { t.Skip("skip postgres due to it only allow unique constraint matching given keys") } + if name := DB.Dialector.Name(); name == "gaussdb" { + t.Skip("skip gaussdb due to it only allow unique constraint matching given keys") + } + DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil { t.Fatalf("Failed to auto migrate, got error: %v", err) diff --git a/tests/postgres_test.go b/tests/postgres_test.go index 44cac6bf..cd59723f 100644 --- a/tests/postgres_test.go +++ b/tests/postgres_test.go @@ -12,7 +12,7 @@ import ( ) func TestPostgresReturningIDWhichHasStringType(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { t.Skip() } @@ -62,7 +62,7 @@ func TestPostgresReturningIDWhichHasStringType(t *testing.T) { } func TestPostgres(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { t.Skip() } @@ -166,7 +166,7 @@ type Category struct { } func TestMany2ManyWithDefaultValueUUID(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { t.Skip() } @@ -191,7 +191,7 @@ func TestMany2ManyWithDefaultValueUUID(t *testing.T) { } func TestPostgresOnConstraint(t *testing.T) { - if DB.Dialector.Name() != "postgres" { + if DB.Dialector.Name() != "postgres" || DB.Dialector.Name() != "gaussdb" { t.Skip() } diff --git a/tests/serializer_test.go b/tests/serializer_test.go index f1b8a336..dbcc49e4 100644 --- a/tests/serializer_test.go +++ b/tests/serializer_test.go @@ -45,7 +45,7 @@ type SerializerPostgresStruct struct { func (*SerializerPostgresStruct) TableName() string { return "serializer_structs" } func adaptorSerializerModel(s *SerializerStruct) interface{} { - if DB.Dialector.Name() == "postgres" { + if DB.Dialector.Name() == "postgres" || DB.Dialector.Name() == "gaussdb" { sps := SerializerPostgresStruct(*s) return &sps } diff --git a/tests/sql_builder_test.go b/tests/sql_builder_test.go index 0c204db4..13fcb648 100644 --- a/tests/sql_builder_test.go +++ b/tests/sql_builder_test.go @@ -487,7 +487,7 @@ func replaceQuoteInSQL(sql string) string { // convert dialect special quote into double quote switch DB.Dialector.Name() { - case "postgres": + case "postgres", "gaussdb": sql = strings.ReplaceAll(sql, `"`, `"`) case "mysql", "sqlite": sql = strings.ReplaceAll(sql, "`", `"`) diff --git a/tests/table_test.go b/tests/table_test.go index 0d44a15b..a23b6ed3 100644 --- a/tests/table_test.go +++ b/tests/table_test.go @@ -5,6 +5,7 @@ import ( "sync" "testing" + "github.com/moseszane168/gaussdb" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/schema" @@ -251,6 +252,82 @@ func TestPostgresTableWithIdentifierLength(t *testing.T) { }) } +func TestPostgresTableWithIdentifierLengthGaussDB(t *testing.T) { + if DB.Dialector.Name() != "gaussdb" { + return + } + + type LongString struct { + ThisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString string `gorm:"unique"` + } + + t.Run("default", func(t *testing.T) { + db, _ := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{}) + user, err := schema.Parse(&LongString{}, &sync.Map{}, db.Config.NamingStrategy) + if err != nil { + t.Fatalf("failed to parse user unique, got error %v", err) + } + + constraints := user.ParseUniqueConstraints() + if len(constraints) != 1 { + t.Fatalf("failed to find unique constraint, got %v", constraints) + } + + for key := range constraints { + if len(key) != 63 { + t.Errorf("failed to find unique constraint, got %v", constraints) + } + } + }) + + t.Run("naming strategy", func(t *testing.T) { + db, _ := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{ + NamingStrategy: schema.NamingStrategy{}, + }) + + user, err := schema.Parse(&LongString{}, &sync.Map{}, db.Config.NamingStrategy) + if err != nil { + t.Fatalf("failed to parse user unique, got error %v", err) + } + + constraints := user.ParseUniqueConstraints() + if len(constraints) != 1 { + t.Fatalf("failed to find unique constraint, got %v", constraints) + } + + for key := range constraints { + if len(key) != 63 { + t.Errorf("failed to find unique constraint, got %v", constraints) + } + } + }) + + t.Run("namer", func(t *testing.T) { + uname := "custom_unique_name" + db, _ := gorm.Open(gaussdb.Open(gaussdbDSN), &gorm.Config{ + NamingStrategy: mockUniqueNamingStrategy{ + UName: uname, + }, + }) + + user, err := schema.Parse(&LongString{}, &sync.Map{}, db.Config.NamingStrategy) + if err != nil { + t.Fatalf("failed to parse user unique, got error %v", err) + } + + constraints := user.ParseUniqueConstraints() + if len(constraints) != 1 { + t.Fatalf("failed to find unique constraint, got %v", constraints) + } + + for key := range constraints { + if key != uname { + t.Errorf("failed to find unique constraint, got %v", constraints) + } + } + }) +} + type mockUniqueNamingStrategy struct { UName string schema.NamingStrategy diff --git a/tests/tests_test.go b/tests/tests_test.go index e1b33ea7..5b11459b 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -8,6 +8,7 @@ import ( "path/filepath" "time" + "github.com/moseszane168/gaussdb" "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" @@ -21,6 +22,7 @@ var DB *gorm.DB var ( mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local" postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai" + gaussdbDSN = "user=gaussdb password=Gaussdb@123 dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai" sqlserverDSN = "sqlserver://sa:LoremIpsum86@localhost:9930?database=master" tidbDSN = "root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local" ) @@ -65,6 +67,15 @@ func OpenTestConnection(cfg *gorm.Config) (db *gorm.DB, err error) { DSN: dbDSN, PreferSimpleProtocol: true, }), cfg) + case "gaussdb": + log.Println("testing gaussdb...") + if dbDSN == "" { + dbDSN = gaussdbDSN + } + db, err = gorm.Open(gaussdb.New(gaussdb.Config{ + DSN: dbDSN, + PreferSimpleProtocol: true, + }), cfg) case "sqlserver": // go install github.com/microsoft/go-sqlcmd/cmd/sqlcmd@latest // SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930 diff --git a/tests/update_test.go b/tests/update_test.go index 9eb9dbfc..1e3216af 100644 --- a/tests/update_test.go +++ b/tests/update_test.go @@ -765,9 +765,9 @@ func TestSaveWithPrimaryValue(t *testing.T) { } } -// only sqlite, postgres, sqlserver support returning +// only sqlite, postgres, gaussdb, sqlserver support returning func TestUpdateReturning(t *testing.T) { - if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlserver" { + if DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlserver" { return } @@ -883,9 +883,9 @@ func TestSaveWithHooks(t *testing.T) { } } -// only postgres, sqlserver, sqlite support update from +// only postgres, gaussdb, sqlserver, sqlite support update from func TestUpdateFrom(t *testing.T) { - if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "sqlserver" { + if DB.Dialector.Name() != "postgres" && DB.Dialector.Name() != "gaussdb" && DB.Dialector.Name() != "sqlite" && DB.Dialector.Name() != "sqlserver" { return }