From 90331d85bf54ee9ec2fc39275b57b0b22cf18e8f Mon Sep 17 00:00:00 2001 From: Jack Ling <34231795+lingcoder@users.noreply.github.com> Date: Wed, 11 Feb 2026 14:40:46 +0800 Subject: [PATCH] test(contrib/drivers/gaussdb): add union, DO, raw where test coverage (#4687) ## Summary - Port 2 test files, 1 testdata SQL, and append Test_Raw_Where from PgSQL driver to GaussDB driver - Add `gaussdb_z_unit_feature_union_test.go` (4 tests): Union/UnionAll query operations - Add `gaussdb_z_unit_feature_model_do_test.go` (10 tests): DO struct-based CRUD operations - Append `Test_Raw_Where` to `gaussdb_z_unit_raw_test.go` (1 test): raw SQL in Where with subquery and column comparison - Add `testdata/table_with_prefix.sql` for DO prefix tests - **15 new test functions**, ~605 net new lines ## Test plan - [x] `go build ./...` passes - [x] `gofmt` and `gci` applied - [x] No remaining `pgsql` references in new files - [ ] Run full test suite against GaussDB instance ref #4689 --------- Co-authored-by: John Guo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../gaussdb_z_unit_feature_model_do_test.go | 410 ++++++++++++++++++ .../gaussdb_z_unit_feature_union_test.go | 146 +++++++ .../gaussdb/gaussdb_z_unit_raw_test.go | 43 ++ .../gaussdb/testdata/table_with_prefix.sql | 6 + 4 files changed, 605 insertions(+) create mode 100644 contrib/drivers/gaussdb/gaussdb_z_unit_feature_model_do_test.go create mode 100644 contrib/drivers/gaussdb/gaussdb_z_unit_feature_union_test.go create mode 100644 contrib/drivers/gaussdb/testdata/table_with_prefix.sql diff --git a/contrib/drivers/gaussdb/gaussdb_z_unit_feature_model_do_test.go b/contrib/drivers/gaussdb/gaussdb_z_unit_feature_model_do_test.go new file mode 100644 index 000000000..5d6958683 --- /dev/null +++ b/contrib/drivers/gaussdb/gaussdb_z_unit_feature_model_do_test.go @@ -0,0 +1,410 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gaussdb_test + +import ( + "fmt" + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" +) + +// createTableDO creates a table with nullable columns (no NOT NULL constraints) +// suitable for DO (Data Object) partial insert tests. +func createTableDO(table ...string) (name string) { + if len(table) > 0 { + name = table[0] + } else { + name = fmt.Sprintf(`%s_%d`, TablePrefix+"do_test", gtime.TimestampNano()) + } + dropTable(name) + if _, err := db.Exec(ctx, fmt.Sprintf(` + CREATE TABLE %s ( + id bigserial NOT NULL, + passport varchar(45) DEFAULT '', + password varchar(32) DEFAULT '', + nickname varchar(45) DEFAULT '', + create_time timestamp DEFAULT NULL, + PRIMARY KEY (id) + );`, name, + )); err != nil { + gtest.Fatal(err) + } + return +} + +func Test_Model_Insert_Data_DO(t *testing.T) { + table := createTableDO() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + }) +} + +func Test_Model_Insert_Data_List_DO(t *testing.T) { + table := createTableDO() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := g.Slice{ + User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + }, + User{ + Id: 2, + Passport: "user_2", + Password: "pass_2", + }, + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 2) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + + one, err = db.Model(table).WherePri(2).One() + t.AssertNil(err) + t.Assert(one[`id`], 2) + t.Assert(one[`passport`], `user_2`) + t.Assert(one[`password`], `pass_2`) + t.Assert(one[`nickname`], ``) + }) +} + +func Test_Model_Update_Data_DO(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := User{ + Id: 1, + Passport: "user_100", + Password: "pass_100", + } + _, err := db.Model(table).Data(data).WherePri(1).Update() + t.AssertNil(err) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_100`) + t.Assert(one[`password`], `pass_100`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Update_Pointer_Data_DO(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type NN string + type Req struct { + Id int + Passport *string + Password *string + Nickname *NN + } + type UserDo struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + var ( + nickname = NN("nickname_111") + req = Req{ + Password: gconv.PtrString("12345678"), + Nickname: &nickname, + } + data = UserDo{ + Passport: req.Passport, + Password: req.Password, + Nickname: req.Nickname, + } + ) + + _, err := db.Model(table).Data(data).WherePri(1).Update() + t.AssertNil(err) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`password`], `12345678`) + t.Assert(one[`nickname`], `nickname_111`) + }) +} + +func Test_Model_Where_DO(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + where := User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + one, err := db.Model(table).Where(where).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Insert_Data_ForDao(t *testing.T) { + table := createTableDO() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := UserForDao{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + }) +} + +func Test_Model_Insert_Data_List_ForDao(t *testing.T) { + table := createTableDO() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := g.Slice{ + UserForDao{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + }, + UserForDao{ + Id: 2, + Passport: "user_2", + Password: "pass_2", + }, + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 2) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + + one, err = db.Model(table).WherePri(2).One() + t.AssertNil(err) + t.Assert(one[`id`], 2) + t.Assert(one[`passport`], `user_2`) + t.Assert(one[`password`], `pass_2`) + t.Assert(one[`nickname`], ``) + }) +} + +func Test_Model_Update_Data_ForDao(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := UserForDao{ + Id: 1, + Passport: "user_100", + Password: "pass_100", + } + _, err := db.Model(table).Data(data).WherePri(1).Update() + t.AssertNil(err) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_100`) + t.Assert(one[`password`], `pass_100`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Where_ForDao(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + where := UserForDao{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + one, err := db.Model(table).Where(where).One() + t.AssertNil(err) + t.Assert(one[`id`], 1) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Where_FieldPrefix(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := gstr.SplitAndTrim(gtest.DataContent(`table_with_prefix.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable("instance") + + type Instance struct { + ID int `orm:"f_id"` + Name string + } + + type InstanceDo struct { + g.Meta `orm:"table:instance, do:true"` + ID any `orm:"f_id"` + } + var instance *Instance + err := db.Model("instance").Where(InstanceDo{ + ID: 1, + }).Scan(&instance) + t.AssertNil(err) + t.AssertNE(instance, nil) + t.Assert(instance.ID, 1) + t.Assert(instance.Name, "john") + }) + // With omitempty. + gtest.C(t, func(t *gtest.T) { + array := gstr.SplitAndTrim(gtest.DataContent(`table_with_prefix.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable("instance") + + type Instance struct { + ID int `orm:"f_id,omitempty"` + Name string + } + + type InstanceDo struct { + g.Meta `orm:"table:instance, do:true"` + ID any `orm:"f_id,omitempty"` + } + var instance *Instance + err := db.Model("instance").Where(InstanceDo{ + ID: 1, + }).Scan(&instance) + t.AssertNil(err) + t.AssertNE(instance, nil) + t.Assert(instance.ID, 1) + t.Assert(instance.Name, "john") + }) +} diff --git a/contrib/drivers/gaussdb/gaussdb_z_unit_feature_union_test.go b/contrib/drivers/gaussdb/gaussdb_z_unit_feature_union_test.go new file mode 100644 index 000000000..51f401bc6 --- /dev/null +++ b/contrib/drivers/gaussdb/gaussdb_z_unit_feature_union_test.go @@ -0,0 +1,146 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gaussdb_test + +import ( + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/test/gtest" +) + +func Test_Union(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 3) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} + +func Test_UnionAll(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 5) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 2) + t.Assert(r[3]["id"], 1) + t.Assert(r[4]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} + +func Test_Model_Union(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 3) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} + +func Test_Model_UnionAll(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 5) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 2) + t.Assert(r[3]["id"], 1) + t.Assert(r[4]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} diff --git a/contrib/drivers/gaussdb/gaussdb_z_unit_raw_test.go b/contrib/drivers/gaussdb/gaussdb_z_unit_raw_test.go index 4d9c2dcba..7b3870e34 100644 --- a/contrib/drivers/gaussdb/gaussdb_z_unit_raw_test.go +++ b/contrib/drivers/gaussdb/gaussdb_z_unit_raw_test.go @@ -7,6 +7,7 @@ package gaussdb_test import ( + "context" "testing" "github.com/gogf/gf/v2/database/gdb" @@ -97,3 +98,45 @@ func Test_Raw_Update(t *testing.T) { t.Assert(n, int64(1)) }) } + +func Test_Raw_Where(t *testing.T) { + table1 := createTable("test_raw_where_table1") + table2 := createTable("test_raw_where_table2") + defer dropTable(table1) + defer dropTable(table2) + + // https://github.com/gogf/gf/issues/3922 + gtest.C(t, func(t *gtest.T) { + expectSql := `SELECT * FROM "test_raw_where_table1" AS A WHERE NOT EXISTS (SELECT B.id FROM "test_raw_where_table2" AS B WHERE "B"."id"=A.id) LIMIT 1` + sql, err := gdb.ToSQL(ctx, func(ctx context.Context) error { + s := db.Model(table2).As("B").Ctx(ctx).Fields("B.id").Where("B.id", gdb.Raw("A.id")) + m := db.Model(table1).As("A").Ctx(ctx).Where("NOT EXISTS ?", s).Limit(1) + _, err := m.All() + return err + }) + t.AssertNil(err) + t.Assert(expectSql, sql) + }) + gtest.C(t, func(t *gtest.T) { + expectSql := `SELECT * FROM "test_raw_where_table1" AS A WHERE NOT EXISTS (SELECT B.id FROM "test_raw_where_table2" AS B WHERE B.id=A.id) LIMIT 1` + sql, err := gdb.ToSQL(ctx, func(ctx context.Context) error { + s := db.Model(table2).As("B").Ctx(ctx).Fields("B.id").Where(gdb.Raw("B.id=A.id")) + m := db.Model(table1).As("A").Ctx(ctx).Where("NOT EXISTS ?", s).Limit(1) + _, err := m.All() + return err + }) + t.AssertNil(err) + t.Assert(expectSql, sql) + }) + // https://github.com/gogf/gf/issues/3915 + gtest.C(t, func(t *gtest.T) { + expectSql := `SELECT * FROM "test_raw_where_table1" WHERE "passport" < "nickname"` + sql, err := gdb.ToSQL(ctx, func(ctx context.Context) error { + m := db.Model(table1).Ctx(ctx).WhereLT("passport", gdb.Raw(`"nickname"`)) + _, err := m.All() + return err + }) + t.AssertNil(err) + t.Assert(expectSql, sql) + }) +} diff --git a/contrib/drivers/gaussdb/testdata/table_with_prefix.sql b/contrib/drivers/gaussdb/testdata/table_with_prefix.sql new file mode 100644 index 000000000..f7dfe2157 --- /dev/null +++ b/contrib/drivers/gaussdb/testdata/table_with_prefix.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS instance; +CREATE TABLE instance ( + f_id SERIAL NOT NULL PRIMARY KEY, + name varchar(255) DEFAULT '' +); +INSERT INTO instance VALUES (1, 'john');