From 3d9cdb89979eaf976e342d5f53c5d90b2fcb7c4f Mon Sep 17 00:00:00 2001 From: PickMeUp Date: Fri, 20 Jun 2025 19:11:01 +0800 Subject: [PATCH] fix(gdb): support multiple order fields in "with" --- .../mysql/mysql_z_unit_feature_with_test.go | 108 ++++++++++++++++++ database/gdb/gdb_model_with.go | 7 +- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go b/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go index 64a491991..30390b4cb 100644 --- a/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go @@ -1888,3 +1888,111 @@ PRIMARY KEY (user_id) t.AssertNil(user3.UserDetail) }) } + +func Test_Table_Relation_WithAll_Order(t *testing.T) { + var ( + tableUser = "user101" + tableUserDetail = "user_detail101" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +name varchar(45) NOT NULL, +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +user_id int(10) unsigned NOT NULL, +address varchar(45) NOT NULL, +deleted_at datetime default NULL , +PRIMARY KEY (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail101"` + UserID int `json:"user_id"` + Address string `json:"address"` + DeletedAt *gtime.Time `json:"deleted_at"` + } + + // For Test Only + type UserEmbedded struct { + ID int `json:"id"` + Name string `json:"name"` + } + + type User struct { + gmeta.Meta `orm:"table:user101"` + UserEmbedded + UserDetail *UserDetail `orm:"with:user_id=id"` + } + type UserWithDeletedDetail struct { + gmeta.Meta `orm:"table:user101"` + UserEmbedded + UserDetail *UserDetail `orm:"with:user_id=id, order:user_id asc,address desc, unscoped:true"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "user_id": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + // Delete detail where i = 3 + if i == 3 { + _, err = db.Delete(ctx, tableUserDetail, g.Map{ + "user_id": i, + }) + } + gtest.AssertNil(err) + } + gtest.C(t, func(t *gtest.T) { + var user0 User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user0) + t.AssertNil(err) + t.Assert(user0.ID, 4) + t.AssertNE(user0.UserDetail, nil) + t.AssertNil(user0.UserDetail.DeletedAt) + t.Assert(user0.UserDetail.UserID, 4) + t.Assert(user0.UserDetail.Address, `address_4`) + + var user1 User + err = db.Model(tableUser).WithAll().Where("id", 3).Scan(&user1) + t.AssertNil(err) + t.Assert(user1.ID, 3) + t.AssertNil(user1.UserDetail) + + var user2 UserWithDeletedDetail + err = db.Model(tableUser).WithAll().Where("id", 3).Scan(&user2) + t.AssertNil(err) + t.Assert(user2.ID, 3) + t.AssertNE(user2.UserDetail, nil) + t.AssertNE(user2.UserDetail.DeletedAt, nil) + t.Assert(user2.UserDetail.UserID, 3) + t.Assert(user2.UserDetail.Address, `address_3`) + + // Unscoped outside test + var user3 User + err = db.Model(tableUser).Unscoped().WithAll().Where("id", 3).Scan(&user3) + t.AssertNil(err) + t.Assert(user3.ID, 3) + t.AssertNil(user3.UserDetail) + }) +} diff --git a/database/gdb/gdb_model_with.go b/database/gdb/gdb_model_with.go index fcd36aeec..8e7e333dd 100644 --- a/database/gdb/gdb_model_with.go +++ b/database/gdb/gdb_model_with.go @@ -333,7 +333,12 @@ func (m *Model) parseWithTagInFieldStruct(field gstructs.Field) (output parseWit key = array[0] data[key] = gstr.Trim(array[1]) } else { - data[key] += " " + gstr.Trim(v) + if key == OrmTagForWithOrder { + // supporting multiple order fields + data[key] += "," + gstr.Trim(v) + } else { + data[key] += " " + gstr.Trim(v) + } } } output.With = data[OrmTagForWith]