From ad9d605e279c5e8f7240a8162385b3a061b200ec Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Sat, 20 Aug 2022 19:21:22 +0300 Subject: [PATCH] entc/gen: ensure immutability is consistent between edge and their fields --- doc/md/privacy.md | 3 +- entc/gen/type.go | 16 ++- .../edgefield/ent/rental_update.go | 106 ------------------ .../edgefield/ent/schema/rental.go | 9 +- entc/integration/edgefield/ent/schema/user.go | 3 +- .../edgeschema/ent/friendship_create.go | 18 +++ .../edgeschema/ent/internal/schema.go | 2 +- .../edgeschema/ent/schema/friendship.go | 6 +- examples/privacytenant/ent/internal/schema.go | 2 +- examples/privacytenant/ent/schema/mixin.go | 3 +- 10 files changed, 47 insertions(+), 121 deletions(-) diff --git a/doc/md/privacy.md b/doc/md/privacy.md index 42f9b90b3a..8063c61851 100644 --- a/doc/md/privacy.md +++ b/doc/md/privacy.md @@ -383,7 +383,8 @@ type TenantMixin struct { // Fields for all schemas that embed TenantMixin. func (TenantMixin) Fields() []ent.Field { return []ent.Field{ - field.Int("tenant_id"), + field.Int("tenant_id"). + Immutable(), } } diff --git a/entc/gen/type.go b/entc/gen/type.go index 074b40c77b..3aa473af0a 100644 --- a/entc/gen/type.go +++ b/entc/gen/type.go @@ -724,11 +724,17 @@ func (t *Type) setupFieldEdge(fk *ForeignKey, fkOwner *Edge, fkName string) erro if !ok { return fmt.Errorf("field %q was not found in the schema for edge %q", fkName, fkOwner.Name) } - if tf.Optional != fkOwner.Optional { - return fmt.Errorf("mismatch optional/required config for edge %q and field %q", fkOwner.Name, fkName) - } - if tf.Immutable { - return fmt.Errorf("field edge %q cannot be immutable", fkName) + switch tf, ok := t.fields[fkName]; { + case !ok: + return fmt.Errorf("field %q was not found in the schema for edge %q", fkName, fkOwner.Name) + case tf.Optional && !fkOwner.Optional: + return fmt.Errorf("edge-field %q was set as Optional, but edge %q is not", fkName, fkOwner.Name) + case !tf.Optional && fkOwner.Optional: + return fmt.Errorf("edge %q was set as Optional, but edge-field %q is not", fkOwner.Name, fkName) + case tf.Immutable && !fkOwner.Immutable: + return fmt.Errorf("edge-field %q was set as Immutable, but edge %q is not", fkName, fkOwner.Name) + case !tf.Immutable && fkOwner.Immutable: + return fmt.Errorf("edge %q was set as Immutable, but edge-field %q is not", fkOwner.Name, fkName) } if t1, t2 := tf.Type.Type, fkOwner.Type.ID.Type.Type; t1 != t2 { return fmt.Errorf("mismatch field type between edge field %q and id of type %q (%s != %s)", fkName, fkOwner.Type.Name, t1, t2) diff --git a/entc/integration/edgefield/ent/rental_update.go b/entc/integration/edgefield/ent/rental_update.go index cac3d26322..2c9a692403 100644 --- a/entc/integration/edgefield/ent/rental_update.go +++ b/entc/integration/edgefield/ent/rental_update.go @@ -14,11 +14,9 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" - "entgo.io/ent/entc/integration/edgefield/ent/car" "entgo.io/ent/entc/integration/edgefield/ent/predicate" "entgo.io/ent/entc/integration/edgefield/ent/rental" "entgo.io/ent/schema/field" - "github.com/google/uuid" ) // RentalUpdate is the builder for updating Rental entities. @@ -48,28 +46,11 @@ func (ru *RentalUpdate) SetNillableDate(t *time.Time) *RentalUpdate { return ru } -// SetCarID sets the "car_id" field. -func (ru *RentalUpdate) SetCarID(u uuid.UUID) *RentalUpdate { - ru.mutation.SetCarID(u) - return ru -} - -// SetCar sets the "car" edge to the Car entity. -func (ru *RentalUpdate) SetCar(c *Car) *RentalUpdate { - return ru.SetCarID(c.ID) -} - // Mutation returns the RentalMutation object of the builder. func (ru *RentalUpdate) Mutation() *RentalMutation { return ru.mutation } -// ClearCar clears the "car" edge to the Car entity. -func (ru *RentalUpdate) ClearCar() *RentalUpdate { - ru.mutation.ClearCar() - return ru -} - // Save executes the query and returns the number of nodes affected by the update operation. func (ru *RentalUpdate) Save(ctx context.Context) (int, error) { var ( @@ -166,41 +147,6 @@ func (ru *RentalUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: rental.FieldDate, }) } - if ru.mutation.CarCleared() { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: rental.CarTable, - Columns: []string{rental.CarColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: &sqlgraph.FieldSpec{ - Type: field.TypeUUID, - Column: car.FieldID, - }, - }, - } - _spec.Edges.Clear = append(_spec.Edges.Clear, edge) - } - if nodes := ru.mutation.CarIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: rental.CarTable, - Columns: []string{rental.CarColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: &sqlgraph.FieldSpec{ - Type: field.TypeUUID, - Column: car.FieldID, - }, - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _spec.Edges.Add = append(_spec.Edges.Add, edge) - } if n, err = sqlgraph.UpdateNodes(ctx, ru.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{rental.Label} @@ -234,28 +180,11 @@ func (ruo *RentalUpdateOne) SetNillableDate(t *time.Time) *RentalUpdateOne { return ruo } -// SetCarID sets the "car_id" field. -func (ruo *RentalUpdateOne) SetCarID(u uuid.UUID) *RentalUpdateOne { - ruo.mutation.SetCarID(u) - return ruo -} - -// SetCar sets the "car" edge to the Car entity. -func (ruo *RentalUpdateOne) SetCar(c *Car) *RentalUpdateOne { - return ruo.SetCarID(c.ID) -} - // Mutation returns the RentalMutation object of the builder. func (ruo *RentalUpdateOne) Mutation() *RentalMutation { return ruo.mutation } -// ClearCar clears the "car" edge to the Car entity. -func (ruo *RentalUpdateOne) ClearCar() *RentalUpdateOne { - ruo.mutation.ClearCar() - return ruo -} - // Select allows selecting one or more fields (columns) of the returned entity. // The default is selecting all fields defined in the entity schema. func (ruo *RentalUpdateOne) Select(field string, fields ...string) *RentalUpdateOne { @@ -382,41 +311,6 @@ func (ruo *RentalUpdateOne) sqlSave(ctx context.Context) (_node *Rental, err err Column: rental.FieldDate, }) } - if ruo.mutation.CarCleared() { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: rental.CarTable, - Columns: []string{rental.CarColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: &sqlgraph.FieldSpec{ - Type: field.TypeUUID, - Column: car.FieldID, - }, - }, - } - _spec.Edges.Clear = append(_spec.Edges.Clear, edge) - } - if nodes := ruo.mutation.CarIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: rental.CarTable, - Columns: []string{rental.CarColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: &sqlgraph.FieldSpec{ - Type: field.TypeUUID, - Column: car.FieldID, - }, - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _spec.Edges.Add = append(_spec.Edges.Add, edge) - } _node = &Rental{config: ruo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/entc/integration/edgefield/ent/schema/rental.go b/entc/integration/edgefield/ent/schema/rental.go index 0974672799..1cdc7c76d9 100644 --- a/entc/integration/edgefield/ent/schema/rental.go +++ b/entc/integration/edgefield/ent/schema/rental.go @@ -25,8 +25,10 @@ func (Rental) Fields() []ent.Field { return []ent.Field{ field.Time("date"). Default(time.Now), - field.Int("user_id"), - field.UUID("car_id", uuid.UUID{}), + field.Int("user_id"). + Immutable(), + field.UUID("car_id", uuid.UUID{}). + Immutable(), } } @@ -43,7 +45,8 @@ func (Rental) Edges() []ent.Edge { Ref("rentals"). Field("car_id"). Unique(). - Required(), + Required(). + Immutable(), } } diff --git a/entc/integration/edgefield/ent/schema/user.go b/entc/integration/edgefield/ent/schema/user.go index 151b66fca7..c197ddd464 100644 --- a/entc/integration/edgefield/ent/schema/user.go +++ b/entc/integration/edgefield/ent/schema/user.go @@ -25,7 +25,8 @@ func (User) Fields() []ent.Field { }). Immutable(), field.Int("parent_id"). - Optional(), + Optional(). + Immutable(), field.Int("spouse_id"). Optional(), } diff --git a/entc/integration/edgeschema/ent/friendship_create.go b/entc/integration/edgeschema/ent/friendship_create.go index d8bec1c208..2714c81742 100644 --- a/entc/integration/edgeschema/ent/friendship_create.go +++ b/entc/integration/edgeschema/ent/friendship_create.go @@ -360,6 +360,14 @@ func (u *FriendshipUpsert) UpdateCreatedAt() *FriendshipUpsert { // Exec(ctx) func (u *FriendshipUpsertOne) UpdateNewValues() *FriendshipUpsertOne { u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.UserID(); exists { + s.SetIgnore(friendship.FieldUserID) + } + if _, exists := u.create.mutation.FriendID(); exists { + s.SetIgnore(friendship.FieldFriendID) + } + })) return u } @@ -595,6 +603,16 @@ type FriendshipUpsertBulk struct { // Exec(ctx) func (u *FriendshipUpsertBulk) UpdateNewValues() *FriendshipUpsertBulk { u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.UserID(); exists { + s.SetIgnore(friendship.FieldUserID) + } + if _, exists := b.mutation.FriendID(); exists { + s.SetIgnore(friendship.FieldFriendID) + } + } + })) return u } diff --git a/entc/integration/edgeschema/ent/internal/schema.go b/entc/integration/edgeschema/ent/internal/schema.go index 2d99e78368..9b7b4b8315 100644 --- a/entc/integration/edgeschema/ent/internal/schema.go +++ b/entc/integration/edgeschema/ent/internal/schema.go @@ -10,4 +10,4 @@ // Package internal holds a loadable version of the latest schema. package internal -const Schema = `{"Schema":"entgo.io/ent/entc/integration/edgeschema/ent/schema","Package":"entgo.io/ent/entc/integration/edgeschema/ent","Schemas":[{"name":"Friendship","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true,"immutable":true},{"name":"friend","type":"User","field":"friend_id","unique":true,"required":true,"immutable":true}],"fields":[{"name":"weight","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":1,"default_kind":2,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}},{"name":"friend_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":3,"MixedIn":false,"MixinIndex":0}}],"indexes":[{"fields":["created_at"]}]},{"name":"Group","config":{"Table":""},"edges":[{"name":"users","type":"User","ref_name":"groups","through":{"N":"joined_users","T":"UserGroup"},"inverse":true}],"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"Relationship","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true},{"name":"relative","type":"User","field":"relative_id","unique":true,"required":true},{"name":"info","type":"RelationshipInfo","field":"info_id","unique":true}],"fields":[{"name":"weight","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":1,"default_kind":2,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"relative_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}},{"name":"info_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"optional":true,"position":{"Index":3,"MixedIn":false,"MixinIndex":0}}],"indexes":[{"fields":["weight"]},{"unique":true,"edges":["info"]}],"annotations":{"Fields":{"ID":["user_id","relative_id"],"StructTag":null}}},{"name":"RelationshipInfo","config":{"Table":""},"fields":[{"name":"text","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"Role","config":{"Table":""},"edges":[{"name":"user","type":"User","ref_name":"roles","through":{"N":"roles_users","T":"RoleUser"},"inverse":true}],"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"unique":true,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}}]},{"name":"RoleUser","config":{"Table":""},"edges":[{"name":"role","type":"Role","field":"role_id","unique":true,"required":true},{"name":"user","type":"User","field":"user_id","unique":true,"required":true}],"fields":[{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"role_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}],"annotations":{"Fields":{"ID":["user_id","role_id"],"StructTag":null}}},{"name":"Tag","config":{"Table":""},"edges":[{"name":"tweets","type":"Tweet","through":{"N":"tweet_tags","T":"TweetTag"}}],"fields":[{"name":"value","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"Tweet","config":{"Table":""},"edges":[{"name":"liked_users","type":"User","ref_name":"liked_tweets","through":{"N":"likes","T":"TweetLike"},"inverse":true},{"name":"user","type":"User","ref_name":"tweets","through":{"N":"tweet_user","T":"UserTweet"},"inverse":true,"comment":"The uniqueness is enforced on the edge schema"},{"name":"tags","type":"Tag","ref_name":"tweets","through":{"N":"tweet_tags","T":"TweetTag"},"inverse":true}],"fields":[{"name":"text","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"size":2147483647,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"TweetLike","config":{"Table":""},"edges":[{"name":"tweet","type":"Tweet","field":"tweet_id","unique":true,"required":true},{"name":"user","type":"User","field":"user_id","unique":true,"required":true}],"fields":[{"name":"liked_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"tweet_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":false,"MixinIndex":0}],"annotations":{"Fields":{"ID":["user_id","tweet_id"],"StructTag":null}}},{"name":"TweetTag","config":{"Table":""},"edges":[{"name":"tag","type":"Tag","field":"tag_id","unique":true,"required":true},{"name":"tweet","type":"Tweet","field":"tweet_id","unique":true,"required":true}],"fields":[{"name":"id","type":{"Type":4,"Ident":"uuid.UUID","PkgPath":"github.com/google/uuid","PkgName":"uuid","Nillable":false,"RType":{"Name":"UUID","Ident":"uuid.UUID","Kind":17,"PkgPath":"github.com/google/uuid","Methods":{"ClockSequence":{"In":[],"Out":[{"Name":"int","Ident":"int","Kind":2,"PkgPath":"","Methods":null}]},"Domain":{"In":[],"Out":[{"Name":"Domain","Ident":"uuid.Domain","Kind":8,"PkgPath":"github.com/google/uuid","Methods":null}]},"ID":{"In":[],"Out":[{"Name":"uint32","Ident":"uint32","Kind":10,"PkgPath":"","Methods":null}]},"MarshalBinary":{"In":[],"Out":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null},{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"MarshalText":{"In":[],"Out":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null},{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"NodeID":{"In":[],"Out":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null}]},"Scan":{"In":[{"Name":"","Ident":"interface {}","Kind":20,"PkgPath":"","Methods":null}],"Out":[{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"String":{"In":[],"Out":[{"Name":"string","Ident":"string","Kind":24,"PkgPath":"","Methods":null}]},"Time":{"In":[],"Out":[{"Name":"Time","Ident":"uuid.Time","Kind":6,"PkgPath":"github.com/google/uuid","Methods":null}]},"URN":{"In":[],"Out":[{"Name":"string","Ident":"string","Kind":24,"PkgPath":"","Methods":null}]},"UnmarshalBinary":{"In":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null}],"Out":[{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"UnmarshalText":{"In":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null}],"Out":[{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"Value":{"In":[],"Out":[{"Name":"Value","Ident":"driver.Value","Kind":20,"PkgPath":"database/sql/driver","Methods":null},{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"Variant":{"In":[],"Out":[{"Name":"Variant","Ident":"uuid.Variant","Kind":8,"PkgPath":"github.com/google/uuid","Methods":null}]},"Version":{"In":[],"Out":[{"Name":"Version","Ident":"uuid.Version","Kind":8,"PkgPath":"github.com/google/uuid","Methods":null}]}}}},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"added_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"tag_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}},{"name":"tweet_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":3,"MixedIn":false,"MixinIndex":0}}]},{"name":"User","config":{"Table":""},"edges":[{"name":"groups","type":"Group","through":{"N":"joined_groups","T":"UserGroup"}},{"name":"friends","type":"User","through":{"N":"friendships","T":"Friendship"}},{"name":"relatives","type":"User","through":{"N":"relationship","T":"Relationship"}},{"name":"liked_tweets","type":"Tweet","through":{"N":"likes","T":"TweetLike"}},{"name":"tweets","type":"Tweet","through":{"N":"user_tweets","T":"UserTweet"}},{"name":"roles","type":"Role","through":{"N":"roles_users","T":"RoleUser"}}],"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":false,"MixinIndex":0}]},{"name":"UserGroup","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true},{"name":"group","type":"Group","field":"group_id","unique":true,"required":true}],"fields":[{"name":"joined_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"group_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}]},{"name":"UserTweet","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true},{"name":"tweet","type":"Tweet","field":"tweet_id","unique":true,"required":true}],"fields":[{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"tweet_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}],"indexes":[{"unique":true,"fields":["tweet_id"]}]}],"Features":["entql","sql/upsert","privacy","schema/snapshot"]}` +const Schema = `{"Schema":"entgo.io/ent/entc/integration/edgeschema/ent/schema","Package":"entgo.io/ent/entc/integration/edgeschema/ent","Schemas":[{"name":"Friendship","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true,"immutable":true},{"name":"friend","type":"User","field":"friend_id","unique":true,"required":true,"immutable":true}],"fields":[{"name":"weight","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":1,"default_kind":2,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"immutable":true,"position":{"Index":2,"MixedIn":false,"MixinIndex":0}},{"name":"friend_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"immutable":true,"position":{"Index":3,"MixedIn":false,"MixinIndex":0}}],"indexes":[{"fields":["created_at"]}]},{"name":"Group","config":{"Table":""},"edges":[{"name":"users","type":"User","ref_name":"groups","through":{"N":"joined_users","T":"UserGroup"},"inverse":true}],"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"Relationship","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true},{"name":"relative","type":"User","field":"relative_id","unique":true,"required":true},{"name":"info","type":"RelationshipInfo","field":"info_id","unique":true}],"fields":[{"name":"weight","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":1,"default_kind":2,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"relative_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}},{"name":"info_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"optional":true,"position":{"Index":3,"MixedIn":false,"MixinIndex":0}}],"indexes":[{"fields":["weight"]},{"unique":true,"edges":["info"]}],"annotations":{"Fields":{"ID":["user_id","relative_id"],"StructTag":null}}},{"name":"RelationshipInfo","config":{"Table":""},"fields":[{"name":"text","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"Role","config":{"Table":""},"edges":[{"name":"user","type":"User","ref_name":"roles","through":{"N":"roles_users","T":"RoleUser"},"inverse":true}],"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"unique":true,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}}]},{"name":"RoleUser","config":{"Table":""},"edges":[{"name":"role","type":"Role","field":"role_id","unique":true,"required":true},{"name":"user","type":"User","field":"user_id","unique":true,"required":true}],"fields":[{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"role_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}],"annotations":{"Fields":{"ID":["user_id","role_id"],"StructTag":null}}},{"name":"Tag","config":{"Table":""},"edges":[{"name":"tweets","type":"Tweet","through":{"N":"tweet_tags","T":"TweetTag"}}],"fields":[{"name":"value","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"Tweet","config":{"Table":""},"edges":[{"name":"liked_users","type":"User","ref_name":"liked_tweets","through":{"N":"likes","T":"TweetLike"},"inverse":true},{"name":"user","type":"User","ref_name":"tweets","through":{"N":"tweet_user","T":"UserTweet"},"inverse":true,"comment":"The uniqueness is enforced on the edge schema"},{"name":"tags","type":"Tag","ref_name":"tweets","through":{"N":"tweet_tags","T":"TweetTag"},"inverse":true}],"fields":[{"name":"text","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"size":2147483647,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}]},{"name":"TweetLike","config":{"Table":""},"edges":[{"name":"tweet","type":"Tweet","field":"tweet_id","unique":true,"required":true},{"name":"user","type":"User","field":"user_id","unique":true,"required":true}],"fields":[{"name":"liked_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"tweet_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":false,"MixinIndex":0}],"annotations":{"Fields":{"ID":["user_id","tweet_id"],"StructTag":null}}},{"name":"TweetTag","config":{"Table":""},"edges":[{"name":"tag","type":"Tag","field":"tag_id","unique":true,"required":true},{"name":"tweet","type":"Tweet","field":"tweet_id","unique":true,"required":true}],"fields":[{"name":"id","type":{"Type":4,"Ident":"uuid.UUID","PkgPath":"github.com/google/uuid","PkgName":"uuid","Nillable":false,"RType":{"Name":"UUID","Ident":"uuid.UUID","Kind":17,"PkgPath":"github.com/google/uuid","Methods":{"ClockSequence":{"In":[],"Out":[{"Name":"int","Ident":"int","Kind":2,"PkgPath":"","Methods":null}]},"Domain":{"In":[],"Out":[{"Name":"Domain","Ident":"uuid.Domain","Kind":8,"PkgPath":"github.com/google/uuid","Methods":null}]},"ID":{"In":[],"Out":[{"Name":"uint32","Ident":"uint32","Kind":10,"PkgPath":"","Methods":null}]},"MarshalBinary":{"In":[],"Out":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null},{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"MarshalText":{"In":[],"Out":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null},{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"NodeID":{"In":[],"Out":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null}]},"Scan":{"In":[{"Name":"","Ident":"interface {}","Kind":20,"PkgPath":"","Methods":null}],"Out":[{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"String":{"In":[],"Out":[{"Name":"string","Ident":"string","Kind":24,"PkgPath":"","Methods":null}]},"Time":{"In":[],"Out":[{"Name":"Time","Ident":"uuid.Time","Kind":6,"PkgPath":"github.com/google/uuid","Methods":null}]},"URN":{"In":[],"Out":[{"Name":"string","Ident":"string","Kind":24,"PkgPath":"","Methods":null}]},"UnmarshalBinary":{"In":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null}],"Out":[{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"UnmarshalText":{"In":[{"Name":"","Ident":"[]uint8","Kind":23,"PkgPath":"","Methods":null}],"Out":[{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"Value":{"In":[],"Out":[{"Name":"Value","Ident":"driver.Value","Kind":20,"PkgPath":"database/sql/driver","Methods":null},{"Name":"error","Ident":"error","Kind":20,"PkgPath":"","Methods":null}]},"Variant":{"In":[],"Out":[{"Name":"Variant","Ident":"uuid.Variant","Kind":8,"PkgPath":"github.com/google/uuid","Methods":null}]},"Version":{"In":[],"Out":[{"Name":"Version","Ident":"uuid.Version","Kind":8,"PkgPath":"github.com/google/uuid","Methods":null}]}}}},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"added_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"tag_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}},{"name":"tweet_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":3,"MixedIn":false,"MixinIndex":0}}]},{"name":"User","config":{"Table":""},"edges":[{"name":"groups","type":"Group","through":{"N":"joined_groups","T":"UserGroup"}},{"name":"friends","type":"User","through":{"N":"friendships","T":"Friendship"}},{"name":"relatives","type":"User","through":{"N":"relationship","T":"Relationship"}},{"name":"liked_tweets","type":"Tweet","through":{"N":"likes","T":"TweetLike"}},{"name":"tweets","type":"Tweet","through":{"N":"user_tweets","T":"UserTweet"}},{"name":"roles","type":"Role","through":{"N":"roles_users","T":"RoleUser"}}],"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":false,"MixinIndex":0}]},{"name":"UserGroup","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true},{"name":"group","type":"Group","field":"group_id","unique":true,"required":true}],"fields":[{"name":"joined_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"group_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}]},{"name":"UserTweet","config":{"Table":""},"edges":[{"name":"user","type":"User","field":"user_id","unique":true,"required":true},{"name":"tweet","type":"Tweet","field":"tweet_id","unique":true,"required":true}],"fields":[{"name":"created_at","type":{"Type":2,"Ident":"","PkgPath":"time","PkgName":"","Nillable":false,"RType":null},"default":true,"default_kind":19,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"user_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":1,"MixedIn":false,"MixinIndex":0}},{"name":"tweet_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":2,"MixedIn":false,"MixinIndex":0}}],"indexes":[{"unique":true,"fields":["tweet_id"]}]}],"Features":["entql","sql/upsert","privacy","schema/snapshot"]}` diff --git a/entc/integration/edgeschema/ent/schema/friendship.go b/entc/integration/edgeschema/ent/schema/friendship.go index 6fd144b694..0a788983c2 100644 --- a/entc/integration/edgeschema/ent/schema/friendship.go +++ b/entc/integration/edgeschema/ent/schema/friendship.go @@ -25,8 +25,10 @@ func (Friendship) Fields() []ent.Field { Default(1), field.Time("created_at"). Default(time.Now), - field.Int("user_id"), - field.Int("friend_id"), + field.Int("user_id"). + Immutable(), + field.Int("friend_id"). + Immutable(), } } diff --git a/examples/privacytenant/ent/internal/schema.go b/examples/privacytenant/ent/internal/schema.go index 85a8910f2e..b46555890c 100644 --- a/examples/privacytenant/ent/internal/schema.go +++ b/examples/privacytenant/ent/internal/schema.go @@ -10,4 +10,4 @@ // Package internal holds a loadable version of the latest schema. package internal -const Schema = `{"Schema":"entgo.io/ent/examples/privacytenant/ent/schema","Package":"entgo.io/ent/examples/privacytenant/ent","Schemas":[{"name":"Group","config":{"Table":""},"edges":[{"name":"tenant","type":"Tenant","field":"tenant_id","unique":true,"required":true,"immutable":true},{"name":"users","type":"User","ref_name":"groups","inverse":true}],"fields":[{"name":"tenant_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":0,"MixedIn":true,"MixinIndex":1}},{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":true,"MixinIndex":0},{"Index":0,"MixedIn":true,"MixinIndex":1},{"Index":0,"MixedIn":false,"MixinIndex":0}]},{"name":"Tenant","config":{"Table":""},"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"validators":1,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":true,"MixinIndex":0},{"Index":0,"MixedIn":false,"MixinIndex":0}]},{"name":"User","config":{"Table":""},"edges":[{"name":"tenant","type":"Tenant","field":"tenant_id","unique":true,"required":true,"immutable":true},{"name":"groups","type":"Group"}],"fields":[{"name":"tenant_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"position":{"Index":0,"MixedIn":true,"MixinIndex":1}},{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"foods","type":{"Type":3,"Ident":"[]string","PkgPath":"","PkgName":"","Nillable":true,"RType":{"Name":"","Ident":"[]string","Kind":23,"PkgPath":"","Methods":{}}},"optional":true,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":true,"MixinIndex":0},{"Index":0,"MixedIn":true,"MixinIndex":1}]}],"Features":["privacy","entql","schema/snapshot"]}` +const Schema = `{"Schema":"entgo.io/ent/examples/privacytenant/ent/schema","Package":"entgo.io/ent/examples/privacytenant/ent","Schemas":[{"name":"Group","config":{"Table":""},"edges":[{"name":"tenant","type":"Tenant","field":"tenant_id","unique":true,"required":true,"immutable":true},{"name":"users","type":"User","ref_name":"groups","inverse":true}],"fields":[{"name":"tenant_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"immutable":true,"position":{"Index":0,"MixedIn":true,"MixinIndex":1}},{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":true,"MixinIndex":0},{"Index":0,"MixedIn":true,"MixinIndex":1},{"Index":0,"MixedIn":false,"MixinIndex":0}]},{"name":"Tenant","config":{"Table":""},"fields":[{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"validators":1,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":true,"MixinIndex":0},{"Index":0,"MixedIn":false,"MixinIndex":0}]},{"name":"User","config":{"Table":""},"edges":[{"name":"tenant","type":"Tenant","field":"tenant_id","unique":true,"required":true,"immutable":true},{"name":"groups","type":"Group"}],"fields":[{"name":"tenant_id","type":{"Type":12,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"immutable":true,"position":{"Index":0,"MixedIn":true,"MixinIndex":1}},{"name":"name","type":{"Type":7,"Ident":"","PkgPath":"","PkgName":"","Nillable":false,"RType":null},"default":true,"default_value":"Unknown","default_kind":24,"position":{"Index":0,"MixedIn":false,"MixinIndex":0}},{"name":"foods","type":{"Type":3,"Ident":"[]string","PkgPath":"","PkgName":"","Nillable":true,"RType":{"Name":"","Ident":"[]string","Kind":23,"PkgPath":"","Methods":{}}},"optional":true,"position":{"Index":1,"MixedIn":false,"MixinIndex":0}}],"policy":[{"Index":0,"MixedIn":true,"MixinIndex":0},{"Index":0,"MixedIn":true,"MixinIndex":1}]}],"Features":["privacy","entql","schema/snapshot"]}` diff --git a/examples/privacytenant/ent/schema/mixin.go b/examples/privacytenant/ent/schema/mixin.go index 4013e8f818..33d25f0a2b 100644 --- a/examples/privacytenant/ent/schema/mixin.go +++ b/examples/privacytenant/ent/schema/mixin.go @@ -42,7 +42,8 @@ type TenantMixin struct { // Fields for all schemas that embed TenantMixin. func (TenantMixin) Fields() []ent.Field { return []ent.Field{ - field.Int("tenant_id"), + field.Int("tenant_id"). + Immutable(), } }