Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

database/gdb: add unscoped tag support for orm struct #3464

Merged
merged 4 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
110 changes: 110 additions & 0 deletions contrib/drivers/mysql/mysql_z_unit_feature_with_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"fmt"
"testing"

"github.com/gogf/gf/v2/os/gtime"

"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
Expand Down Expand Up @@ -1988,3 +1990,111 @@ PRIMARY KEY (id)
t.Assert(user.UserScores[4].Score, 5)
})
}

func Test_Table_Relation_WithAll_Unscoped(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, 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)
})
}
13 changes: 7 additions & 6 deletions database/gdb/gdb_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,13 @@ type iTableName interface {
}

const (
OrmTagForStruct = "orm"
OrmTagForTable = "table"
OrmTagForWith = "with"
OrmTagForWithWhere = "where"
OrmTagForWithOrder = "order"
OrmTagForDo = "do"
OrmTagForStruct = "orm"
OrmTagForTable = "table"
OrmTagForWith = "with"
OrmTagForWithWhere = "where"
OrmTagForWithOrder = "order"
OrmTagForWithUnscoped = "unscoped"
OrmTagForDo = "do"
)

var (
Expand Down
14 changes: 11 additions & 3 deletions database/gdb/gdb_model_with.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ func (m *Model) doWithScanStruct(pointer interface{}) error {
if parsedTagOutput.Order != "" {
model = model.Order(parsedTagOutput.Order)
}
if parsedTagOutput.Unscoped == "true" {
model = model.Unscoped()
}
// With cache feature.
if m.cacheEnabled && m.cacheOption.Name == "" {
model = model.Cache(m.cacheOption)
Expand Down Expand Up @@ -277,6 +280,9 @@ func (m *Model) doWithScanStructs(pointer interface{}) error {
if parsedTagOutput.Order != "" {
model = model.Order(parsedTagOutput.Order)
}
if parsedTagOutput.Unscoped == "true" {
model = model.Unscoped()
}
// With cache feature.
if m.cacheEnabled && m.cacheOption.Name == "" {
model = model.Cache(m.cacheOption)
Expand All @@ -293,9 +299,10 @@ func (m *Model) doWithScanStructs(pointer interface{}) error {
}

type parseWithTagInFieldStructOutput struct {
With string
Where string
Order string
With string
Where string
Order string
Unscoped string
}

func (m *Model) parseWithTagInFieldStruct(field gstructs.Field) (output parseWithTagInFieldStructOutput) {
Expand All @@ -320,5 +327,6 @@ func (m *Model) parseWithTagInFieldStruct(field gstructs.Field) (output parseWit
output.With = data[OrmTagForWith]
output.Where = data[OrmTagForWithWhere]
output.Order = data[OrmTagForWithOrder]
output.Unscoped = data[OrmTagForWithUnscoped]
return
}