Support SubQuery for Generics

This commit is contained in:
Jinzhu 2025-04-20 10:47:00 +08:00
parent 3de6d0b2f9
commit 797a557cc8
4 changed files with 44 additions and 6 deletions

View File

@ -127,6 +127,11 @@ type chainG[T any] struct {
execG[T]
}
func (c chainG[T]) getInstance() *DB {
var r T
return c.g.apply(context.Background()).Model(r).getInstance()
}
func (c chainG[T]) with(op op) chainG[T] {
return chainG[T]{
execG: execG[T]{g: &g[T]{

View File

@ -205,19 +205,20 @@ func (stmt *Statement) AddVar(writer clause.Writer, vars ...interface{}) {
} else {
writer.WriteString("(NULL)")
}
case *DB:
subdb := v.Session(&Session{Logger: logger.Discard, DryRun: true}).getInstance()
if v.Statement.SQL.Len() > 0 {
case interface{ getInstance() *DB }:
cv := v.getInstance()
subdb := cv.Session(&Session{Logger: logger.Discard, DryRun: true}).getInstance()
if cv.Statement.SQL.Len() > 0 {
var (
vars = subdb.Statement.Vars
sql = v.Statement.SQL.String()
sql = cv.Statement.SQL.String()
)
subdb.Statement.Vars = make([]interface{}, 0, len(vars))
for _, vv := range vars {
subdb.Statement.Vars = append(subdb.Statement.Vars, vv)
bindvar := strings.Builder{}
v.Dialector.BindVarTo(&bindvar, subdb.Statement, vv)
cv.Dialector.BindVarTo(&bindvar, subdb.Statement, vv)
sql = strings.Replace(sql, bindvar.String(), "?", 1)
}

View File

@ -366,3 +366,35 @@ func TestGenericsGroupHaving(t *testing.T) {
t.Errorf("expected group name 'GenericsGroupHavingMulti', got '%s'", grouped[0].Name)
}
}
func TestGenericsSubQuery(t *testing.T) {
ctx := context.Background()
users := []User{
{Name: "GenericsSubquery_1", Age: 10},
{Name: "GenericsSubquery_2", Age: 20},
{Name: "GenericsSubquery_3", Age: 30},
{Name: "GenericsSubquery_4", Age: 40},
}
if err := gorm.G[User](DB).CreateInBatches(ctx, &users, len(users)); err != nil {
t.Fatalf("CreateInBatches failed: %v", err)
}
results, err := gorm.G[User](DB).Where("name IN (?)", gorm.G[User](DB).Select("name").Where("name LIKE ?", "GenericsSubquery%")).Find(ctx)
if err != nil {
t.Fatalf("got error: %v", err)
}
if len(results) != 4 {
t.Errorf("Four users should be found, instead found %d", len(results))
}
results, err = gorm.G[User](DB).Where("name IN (?)", gorm.G[User](DB).Select("name").Where("name IN ?", []string{"GenericsSubquery_1", "GenericsSubquery_2"}).Or("name = ?", "GenericsSubquery_3")).Find(ctx)
if err != nil {
t.Fatalf("got error: %v", err)
}
if len(results) != 3 {
t.Errorf("Three users should be found, instead found %d", len(results))
}
}

View File

@ -1,6 +1,6 @@
module gorm.io/gorm/tests
go 1.18.0
go 1.23.0
require (
github.com/google/uuid v1.6.0