diff --git a/generator/templates/client.gotpl b/generator/templates/client.gotpl index 0ef330b..684ce63 100644 --- a/generator/templates/client.gotpl +++ b/generator/templates/client.gotpl @@ -327,11 +327,17 @@ type PredicateData struct { Children []PredicateData } +type ChildPredicate struct { + Column string + Value any +} + type PredicateOf[M any] interface { ToPredicateData() PredicateData Validate() error Column() string Value() any + Children() []ChildPredicate phantom(M) } @@ -355,6 +361,17 @@ func (p Predicate[M]) Value() any { return p.Data.Value } +func (p Predicate[M]) Children() []ChildPredicate { + if !p.Data.IsLogical || len(p.Data.Children) == 0 { + return nil + } + res := make([]ChildPredicate, len(p.Data.Children)) + for i, c := range p.Data.Children { + res[i] = ChildPredicate{Column: c.Column, Value: c.Value} + } + return res +} + func (p Predicate[M]) phantom(M) {} type UniquePredicate[M any] struct { @@ -380,6 +397,17 @@ func (p UniquePredicate[M]) Value() any { return p.Data.Value } +func (p UniquePredicate[M]) Children() []ChildPredicate { + if !p.Data.IsLogical || len(p.Data.Children) == 0 { + return nil + } + res := make([]ChildPredicate, len(p.Data.Children)) + for i, c := range p.Data.Children { + res[i] = ChildPredicate{Column: c.Column, Value: c.Value} + } + return res +} + func (p UniquePredicate[M]) phantom(M) {} func validateValue(col string, val any) error { diff --git a/integration/composite_test.go b/integration/composite_test.go index 139c281..7c4ee1a 100644 --- a/integration/composite_test.go +++ b/integration/composite_test.go @@ -213,6 +213,47 @@ func TestCompositeKeys(t *testing.T) { } }) + t.Run("hook_inspects_composite_Children", func(t *testing.T) { + db, cleanup := setupTestDB(t) + defer cleanup() + + var children []phi.ChildPredicate + + db.User.Use(user.Extension{ + FindUnique: func(ctx context.Context, args *user.FindUniqueArgs, next user.FindUniqueQuery) (*phi.User, error) { + if len(args.Where) > 0 { + children = args.Where[0].Children() + } + return next(ctx, args) + }, + }) + + _, err := db.User.Create(). + SetEmail("hook-children@example.com"). + SetPhoneNum("composite-005b"). + Exec(ctx) + if err != nil { + t.Fatalf("create failed: %v", err) + } + + _, err = db.User.FindUnique( + user.EmailPhone.EQ("hook-children@example.com", "composite-005b"), + ).Exec(ctx) + if err != nil { + t.Fatalf("find unique failed: %v", err) + } + + if len(children) != 2 { + t.Fatalf("expected 2 children, got %d", len(children)) + } + if children[0].Column != "email" || children[0].Value != "hook-children@example.com" { + t.Errorf("unexpected child 0: %+v", children[0]) + } + if children[1].Column != "phoneNum" || children[1].Value != "composite-005b" { + t.Errorf("unexpected child 1: %+v", children[1]) + } + }) + t.Run("hook_replaces_composite_predicate", func(t *testing.T) { db, cleanup := setupTestDB(t) defer cleanup() diff --git a/integration/main.go b/integration/main.go index 9be409c..cc26831 100644 --- a/integration/main.go +++ b/integration/main.go @@ -72,7 +72,6 @@ func main() { // runExtensionExamples(db, ctx) // runCTP(db, ctx) // - usr, err := db.User.Create().SetEmail("xx@yy.com").SetPhoneNum("11").Exec(ctx) if err != nil { panic(err) @@ -84,6 +83,22 @@ func main() { panic(err) } printJSON(posts) + + db.User.Use(user.Extension{ + FindUnique: func(ctx context.Context, args *phi.UserFindUniqueArgs, next phi.UserFindUniqueQuery) (*phi.User, error) { + for _, w := range args.Where { + switch w.Column() { + case user.Email.Column: + // Scalar unique predicate + case user.EmailPhone.Column: + for _, child := range w.Children() { + fmt.Printf("Composite field: %s = %v\n", child.Column, child.Value) + } + } + } + return next(ctx, args) + }, + }) } // ============================================================================= diff --git a/integration/phi/client.go b/integration/phi/client.go index d1bcd37..56d507f 100644 --- a/integration/phi/client.go +++ b/integration/phi/client.go @@ -1293,11 +1293,17 @@ type PredicateData struct { Children []PredicateData } +type ChildPredicate struct { + Column string + Value any +} + type PredicateOf[M any] interface { ToPredicateData() PredicateData Validate() error Column() string Value() any + Children() []ChildPredicate phantom(M) } @@ -1321,6 +1327,17 @@ func (p Predicate[M]) Value() any { return p.Data.Value } +func (p Predicate[M]) Children() []ChildPredicate { + if !p.Data.IsLogical || len(p.Data.Children) == 0 { + return nil + } + res := make([]ChildPredicate, len(p.Data.Children)) + for i, c := range p.Data.Children { + res[i] = ChildPredicate{Column: c.Column, Value: c.Value} + } + return res +} + func (p Predicate[M]) phantom(M) {} type UniquePredicate[M any] struct { @@ -1346,6 +1363,17 @@ func (p UniquePredicate[M]) Value() any { return p.Data.Value } +func (p UniquePredicate[M]) Children() []ChildPredicate { + if !p.Data.IsLogical || len(p.Data.Children) == 0 { + return nil + } + res := make([]ChildPredicate, len(p.Data.Children)) + for i, c := range p.Data.Children { + res[i] = ChildPredicate{Column: c.Column, Value: c.Value} + } + return res +} + func (p UniquePredicate[M]) phantom(M) {} func validateValue(col string, val any) error {