From 62db0faff7f4f7557907acf006988b5861f5c7c0 Mon Sep 17 00:00:00 2001 From: Jannik C Date: Wed, 20 Apr 2022 13:13:28 +0200 Subject: [PATCH 1/4] entc/gen: do no generate `Table()` predicate and warn the user in case of reserved schema name like `Client`. --- entc/gen/graph.go | 16 ++- entc/gen/graph_test.go | 3 + entc/gen/template/where.tmpl | 2 +- entc/integration/ent/comment.go | 12 ++ entc/integration/ent/comment/comment.go | 3 + entc/integration/ent/comment/where.go | 125 ++++++++++++++++++ entc/integration/ent/comment_create.go | 82 ++++++++++++ entc/integration/ent/comment_update.go | 66 +++++++++ entc/integration/ent/entql.go | 6 + entc/integration/ent/migrate/schema.go | 1 + entc/integration/ent/mutation.go | 75 ++++++++++- entc/integration/ent/schema/comment.go | 2 + entc/integration/gremlin/ent/comment.go | 8 ++ .../gremlin/ent/comment/comment.go | 2 + entc/integration/gremlin/ent/comment/where.go | 99 ++++++++++++++ .../integration/gremlin/ent/comment_create.go | 17 +++ .../integration/gremlin/ent/comment_update.go | 52 ++++++++ entc/integration/gremlin/ent/mutation.go | 75 ++++++++++- 18 files changed, 641 insertions(+), 5 deletions(-) diff --git a/entc/gen/graph.go b/entc/gen/graph.go index e20e683a72..35a5368814 100644 --- a/entc/gen/graph.go +++ b/entc/gen/graph.go @@ -142,8 +142,9 @@ func (f GenerateFunc) Generate(g *Graph) error { func NewGraph(c *Config, schemas ...*load.Schema) (g *Graph, err error) { defer catch(&err) g = &Graph{c, make([]*Type, 0, len(schemas)), schemas} - for i := range schemas { - g.addNode(schemas[i]) + for _, s := range schemas { + check(reservedName(s.Name), "add schema %q", s.Name) + g.addNode(s) } for i := range schemas { g.addEdges(schemas[i]) @@ -438,6 +439,17 @@ func resolve(t *Type) error { return nil } +var reservedNames = []string{"Client"} + +func reservedName(n string) error { + for _, rn := range reservedNames { + if rn == n { + return fmt.Errorf("%q is a reserved name and cannot be used as schema name", n) + } + } + return nil +} + // Tables returns the schema definitions of SQL tables for the graph. func (g *Graph) Tables() (all []*schema.Table, err error) { tables := make(map[string]*schema.Table) diff --git a/entc/gen/graph_test.go b/entc/gen/graph_test.go index 61bea6c4a3..3287cae9bb 100644 --- a/entc/gen/graph_test.go +++ b/entc/gen/graph_test.go @@ -130,6 +130,9 @@ func TestNewGraph(t *testing.T) { require.Equal(t2.Edges[5], t2.Edges[6].Ref) require.Equal(map[string]string{"Name": "From"}, t2.Edges[5].Annotations["GQL"]) require.Equal(map[string]string{"Name": "To"}, t2.Edges[6].Annotations["GQL"]) + + _, err = NewGraph(&Config{Package: "entc/gen", Storage: drivers[0]}, &load.Schema{Name: "Client"}) + require.EqualError(err, `entc/gen: add schema "Client": "Client" is a reserved name and cannot be used as schema name`) } func TestNewGraphRequiredLoop(t *testing.T) { diff --git a/entc/gen/template/where.tmpl b/entc/gen/template/where.tmpl index 0949e67895..1199da1ab8 100644 --- a/entc/gen/template/where.tmpl +++ b/entc/gen/template/where.tmpl @@ -41,7 +41,7 @@ func ID(id {{ $.ID.Type }}) predicate.{{ $.Name }} { {{/* JSON cannot be compared using "=" and Enum has a type defined with the field name */}} {{ $hasP := not (or $f.IsJSON $f.IsEnum) }} {{ $comparable := or $f.ConvertedToBasic $f.Type.Valuer }} - {{ $undeclared := (and (ne $func "Label") (ne $func "Hooks") (ne $func "Policy")) }} + {{ $undeclared := (and (ne $func "Label") (ne $func "Hooks") (ne $func "Policy") (ne $func "Table")) }} {{- if and $hasP $comparable $undeclared }} {{ $arg := "v" }} // {{ $func }} applies equality check predicate on the {{ quote $f.Name }} field. It's identical to {{ $func }}EQ. diff --git a/entc/integration/ent/comment.go b/entc/integration/ent/comment.go index e848a5b0e4..078f329474 100644 --- a/entc/integration/ent/comment.go +++ b/entc/integration/ent/comment.go @@ -25,6 +25,8 @@ type Comment struct { UniqueFloat float64 `json:"unique_float,omitempty"` // NillableInt holds the value of the "nillable_int" field. NillableInt *int `json:"nillable_int,omitempty"` + // Table holds the value of the "table" field. + Table string `json:"table,omitempty"` } // scanValues returns the types for scanning values from sql.Rows. @@ -36,6 +38,8 @@ func (*Comment) scanValues(columns []string) ([]interface{}, error) { values[i] = new(sql.NullFloat64) case comment.FieldID, comment.FieldUniqueInt, comment.FieldNillableInt: values[i] = new(sql.NullInt64) + case comment.FieldTable: + values[i] = new(sql.NullString) default: return nil, fmt.Errorf("unexpected column %q for type Comment", columns[i]) } @@ -76,6 +80,12 @@ func (c *Comment) assignValues(columns []string, values []interface{}) error { c.NillableInt = new(int) *c.NillableInt = int(value.Int64) } + case comment.FieldTable: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field table", values[i]) + } else if value.Valid { + c.Table = value.String + } } } return nil @@ -112,6 +122,8 @@ func (c *Comment) String() string { builder.WriteString(", nillable_int=") builder.WriteString(fmt.Sprintf("%v", *v)) } + builder.WriteString(", table=") + builder.WriteString(c.Table) builder.WriteByte(')') return builder.String() } diff --git a/entc/integration/ent/comment/comment.go b/entc/integration/ent/comment/comment.go index 8e53d8e93f..dcf24c90cd 100644 --- a/entc/integration/ent/comment/comment.go +++ b/entc/integration/ent/comment/comment.go @@ -17,6 +17,8 @@ const ( FieldUniqueFloat = "unique_float" // FieldNillableInt holds the string denoting the nillable_int field in the database. FieldNillableInt = "nillable_int" + // FieldTable holds the string denoting the table field in the database. + FieldTable = "table" // Table holds the table name of the comment in the database. Table = "comments" ) @@ -27,6 +29,7 @@ var Columns = []string{ FieldUniqueInt, FieldUniqueFloat, FieldNillableInt, + FieldTable, } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/entc/integration/ent/comment/where.go b/entc/integration/ent/comment/where.go index d81ab00734..92c390ed87 100644 --- a/entc/integration/ent/comment/where.go +++ b/entc/integration/ent/comment/where.go @@ -357,6 +357,131 @@ func NillableIntNotNil() predicate.Comment { }) } +// TableEQ applies the EQ predicate on the "table" field. +func TableEQ(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTable), v)) + }) +} + +// TableNEQ applies the NEQ predicate on the "table" field. +func TableNEQ(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldTable), v)) + }) +} + +// TableIn applies the In predicate on the "table" field. +func TableIn(vs ...string) predicate.Comment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Comment(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldTable), v...)) + }) +} + +// TableNotIn applies the NotIn predicate on the "table" field. +func TableNotIn(vs ...string) predicate.Comment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Comment(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldTable), v...)) + }) +} + +// TableGT applies the GT predicate on the "table" field. +func TableGT(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldTable), v)) + }) +} + +// TableGTE applies the GTE predicate on the "table" field. +func TableGTE(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldTable), v)) + }) +} + +// TableLT applies the LT predicate on the "table" field. +func TableLT(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldTable), v)) + }) +} + +// TableLTE applies the LTE predicate on the "table" field. +func TableLTE(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldTable), v)) + }) +} + +// TableContains applies the Contains predicate on the "table" field. +func TableContains(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldTable), v)) + }) +} + +// TableHasPrefix applies the HasPrefix predicate on the "table" field. +func TableHasPrefix(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldTable), v)) + }) +} + +// TableHasSuffix applies the HasSuffix predicate on the "table" field. +func TableHasSuffix(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldTable), v)) + }) +} + +// TableIsNil applies the IsNil predicate on the "table" field. +func TableIsNil() predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldTable))) + }) +} + +// TableNotNil applies the NotNil predicate on the "table" field. +func TableNotNil() predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldTable))) + }) +} + +// TableEqualFold applies the EqualFold predicate on the "table" field. +func TableEqualFold(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldTable), v)) + }) +} + +// TableContainsFold applies the ContainsFold predicate on the "table" field. +func TableContainsFold(v string) predicate.Comment { + return predicate.Comment(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldTable), v)) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Comment) predicate.Comment { return predicate.Comment(func(s *sql.Selector) { diff --git a/entc/integration/ent/comment_create.go b/entc/integration/ent/comment_create.go index b4cb9b9072..6e2838ea72 100644 --- a/entc/integration/ent/comment_create.go +++ b/entc/integration/ent/comment_create.go @@ -51,6 +51,20 @@ func (cc *CommentCreate) SetNillableNillableInt(i *int) *CommentCreate { return cc } +// SetTable sets the "table" field. +func (cc *CommentCreate) SetTable(s string) *CommentCreate { + cc.mutation.SetTable(s) + return cc +} + +// SetNillableTable sets the "table" field if the given value is not nil. +func (cc *CommentCreate) SetNillableTable(s *string) *CommentCreate { + if s != nil { + cc.SetTable(*s) + } + return cc +} + // Mutation returns the CommentMutation object of the builder. func (cc *CommentCreate) Mutation() *CommentMutation { return cc.mutation @@ -179,6 +193,14 @@ func (cc *CommentCreate) createSpec() (*Comment, *sqlgraph.CreateSpec) { }) _node.NillableInt = &value } + if value, ok := cc.mutation.Table(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: comment.FieldTable, + }) + _node.Table = value + } return _node, _spec } @@ -293,6 +315,24 @@ func (u *CommentUpsert) ClearNillableInt() *CommentUpsert { return u } +// SetTable sets the "table" field. +func (u *CommentUpsert) SetTable(v string) *CommentUpsert { + u.Set(comment.FieldTable, v) + return u +} + +// UpdateTable sets the "table" field to the value that was provided on create. +func (u *CommentUpsert) UpdateTable() *CommentUpsert { + u.SetExcluded(comment.FieldTable) + return u +} + +// ClearTable clears the value of the "table" field. +func (u *CommentUpsert) ClearTable() *CommentUpsert { + u.SetNull(comment.FieldTable) + return u +} + // UpdateNewValues updates the mutable fields using the new values that were set on create. // Using this option is equivalent to using: // @@ -405,6 +445,27 @@ func (u *CommentUpsertOne) ClearNillableInt() *CommentUpsertOne { }) } +// SetTable sets the "table" field. +func (u *CommentUpsertOne) SetTable(v string) *CommentUpsertOne { + return u.Update(func(s *CommentUpsert) { + s.SetTable(v) + }) +} + +// UpdateTable sets the "table" field to the value that was provided on create. +func (u *CommentUpsertOne) UpdateTable() *CommentUpsertOne { + return u.Update(func(s *CommentUpsert) { + s.UpdateTable() + }) +} + +// ClearTable clears the value of the "table" field. +func (u *CommentUpsertOne) ClearTable() *CommentUpsertOne { + return u.Update(func(s *CommentUpsert) { + s.ClearTable() + }) +} + // Exec executes the query. func (u *CommentUpsertOne) Exec(ctx context.Context) error { if len(u.create.conflict) == 0 { @@ -678,6 +739,27 @@ func (u *CommentUpsertBulk) ClearNillableInt() *CommentUpsertBulk { }) } +// SetTable sets the "table" field. +func (u *CommentUpsertBulk) SetTable(v string) *CommentUpsertBulk { + return u.Update(func(s *CommentUpsert) { + s.SetTable(v) + }) +} + +// UpdateTable sets the "table" field to the value that was provided on create. +func (u *CommentUpsertBulk) UpdateTable() *CommentUpsertBulk { + return u.Update(func(s *CommentUpsert) { + s.UpdateTable() + }) +} + +// ClearTable clears the value of the "table" field. +func (u *CommentUpsertBulk) ClearTable() *CommentUpsertBulk { + return u.Update(func(s *CommentUpsert) { + s.ClearTable() + }) +} + // Exec executes the query. func (u *CommentUpsertBulk) Exec(ctx context.Context) error { for i, b := range u.create.builders { diff --git a/entc/integration/ent/comment_update.go b/entc/integration/ent/comment_update.go index b0b445db10..cbc620643f 100644 --- a/entc/integration/ent/comment_update.go +++ b/entc/integration/ent/comment_update.go @@ -84,6 +84,26 @@ func (cu *CommentUpdate) ClearNillableInt() *CommentUpdate { return cu } +// SetTable sets the "table" field. +func (cu *CommentUpdate) SetTable(s string) *CommentUpdate { + cu.mutation.SetTable(s) + return cu +} + +// SetNillableTable sets the "table" field if the given value is not nil. +func (cu *CommentUpdate) SetNillableTable(s *string) *CommentUpdate { + if s != nil { + cu.SetTable(*s) + } + return cu +} + +// ClearTable clears the value of the "table" field. +func (cu *CommentUpdate) ClearTable() *CommentUpdate { + cu.mutation.ClearTable() + return cu +} + // Mutation returns the CommentMutation object of the builder. func (cu *CommentUpdate) Mutation() *CommentMutation { return cu.mutation @@ -209,6 +229,19 @@ func (cu *CommentUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: comment.FieldNillableInt, }) } + if value, ok := cu.mutation.Table(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: comment.FieldTable, + }) + } + if cu.mutation.TableCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: comment.FieldTable, + }) + } if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{comment.Label} @@ -281,6 +314,26 @@ func (cuo *CommentUpdateOne) ClearNillableInt() *CommentUpdateOne { return cuo } +// SetTable sets the "table" field. +func (cuo *CommentUpdateOne) SetTable(s string) *CommentUpdateOne { + cuo.mutation.SetTable(s) + return cuo +} + +// SetNillableTable sets the "table" field if the given value is not nil. +func (cuo *CommentUpdateOne) SetNillableTable(s *string) *CommentUpdateOne { + if s != nil { + cuo.SetTable(*s) + } + return cuo +} + +// ClearTable clears the value of the "table" field. +func (cuo *CommentUpdateOne) ClearTable() *CommentUpdateOne { + cuo.mutation.ClearTable() + return cuo +} + // Mutation returns the CommentMutation object of the builder. func (cuo *CommentUpdateOne) Mutation() *CommentMutation { return cuo.mutation @@ -430,6 +483,19 @@ func (cuo *CommentUpdateOne) sqlSave(ctx context.Context) (_node *Comment, err e Column: comment.FieldNillableInt, }) } + if value, ok := cuo.mutation.Table(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: comment.FieldTable, + }) + } + if cuo.mutation.TableCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: comment.FieldTable, + }) + } _node = &Comment{config: cuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/entc/integration/ent/entql.go b/entc/integration/ent/entql.go index ff81a67825..98aef21d4c 100644 --- a/entc/integration/ent/entql.go +++ b/entc/integration/ent/entql.go @@ -64,6 +64,7 @@ var schemaGraph = func() *sqlgraph.Schema { comment.FieldUniqueInt: {Type: field.TypeInt, Column: comment.FieldUniqueInt}, comment.FieldUniqueFloat: {Type: field.TypeFloat64, Column: comment.FieldUniqueFloat}, comment.FieldNillableInt: {Type: field.TypeInt, Column: comment.FieldNillableInt}, + comment.FieldTable: {Type: field.TypeString, Column: comment.FieldTable}, }, } graph.Nodes[2] = &sqlgraph.Node{ @@ -799,6 +800,11 @@ func (f *CommentFilter) WhereNillableInt(p entql.IntP) { f.Where(p.Field(comment.FieldNillableInt)) } +// WhereTable applies the entql string predicate on the table field. +func (f *CommentFilter) WhereTable(p entql.StringP) { + f.Where(p.Field(comment.FieldTable)) +} + // addPredicate implements the predicateAdder interface. func (ftq *FieldTypeQuery) addPredicate(pred func(s *sql.Selector)) { ftq.predicates = append(ftq.predicates, pred) diff --git a/entc/integration/ent/migrate/schema.go b/entc/integration/ent/migrate/schema.go index ad47afaaae..08d4cc9b65 100644 --- a/entc/integration/ent/migrate/schema.go +++ b/entc/integration/ent/migrate/schema.go @@ -60,6 +60,7 @@ var ( {Name: "unique_int", Type: field.TypeInt, Unique: true}, {Name: "unique_float", Type: field.TypeFloat64, Unique: true}, {Name: "nillable_int", Type: field.TypeInt, Nullable: true}, + {Name: "table", Type: field.TypeString, Nullable: true}, } // CommentsTable holds the schema information for the "comments" table. CommentsTable = &schema.Table{ diff --git a/entc/integration/ent/mutation.go b/entc/integration/ent/mutation.go index 25be4bed24..28837f4891 100644 --- a/entc/integration/ent/mutation.go +++ b/entc/integration/ent/mutation.go @@ -812,6 +812,7 @@ type CommentMutation struct { addunique_float *float64 nillable_int *int addnillable_int *int + table *string clearedFields map[string]struct{} done bool oldValue func(context.Context) (*Comment, error) @@ -1098,6 +1099,55 @@ func (m *CommentMutation) ResetNillableInt() { delete(m.clearedFields, comment.FieldNillableInt) } +// SetTable sets the "table" field. +func (m *CommentMutation) SetTable(s string) { + m.table = &s +} + +// Table returns the value of the "table" field in the mutation. +func (m *CommentMutation) Table() (r string, exists bool) { + v := m.table + if v == nil { + return + } + return *v, true +} + +// OldTable returns the old "table" field's value of the Comment entity. +// If the Comment object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CommentMutation) OldTable(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTable is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTable requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTable: %w", err) + } + return oldValue.Table, nil +} + +// ClearTable clears the value of the "table" field. +func (m *CommentMutation) ClearTable() { + m.table = nil + m.clearedFields[comment.FieldTable] = struct{}{} +} + +// TableCleared returns if the "table" field was cleared in this mutation. +func (m *CommentMutation) TableCleared() bool { + _, ok := m.clearedFields[comment.FieldTable] + return ok +} + +// ResetTable resets all changes to the "table" field. +func (m *CommentMutation) ResetTable() { + m.table = nil + delete(m.clearedFields, comment.FieldTable) +} + // Where appends a list predicates to the CommentMutation builder. func (m *CommentMutation) Where(ps ...predicate.Comment) { m.predicates = append(m.predicates, ps...) @@ -1117,7 +1167,7 @@ func (m *CommentMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *CommentMutation) Fields() []string { - fields := make([]string, 0, 3) + fields := make([]string, 0, 4) if m.unique_int != nil { fields = append(fields, comment.FieldUniqueInt) } @@ -1127,6 +1177,9 @@ func (m *CommentMutation) Fields() []string { if m.nillable_int != nil { fields = append(fields, comment.FieldNillableInt) } + if m.table != nil { + fields = append(fields, comment.FieldTable) + } return fields } @@ -1141,6 +1194,8 @@ func (m *CommentMutation) Field(name string) (ent.Value, bool) { return m.UniqueFloat() case comment.FieldNillableInt: return m.NillableInt() + case comment.FieldTable: + return m.Table() } return nil, false } @@ -1156,6 +1211,8 @@ func (m *CommentMutation) OldField(ctx context.Context, name string) (ent.Value, return m.OldUniqueFloat(ctx) case comment.FieldNillableInt: return m.OldNillableInt(ctx) + case comment.FieldTable: + return m.OldTable(ctx) } return nil, fmt.Errorf("unknown Comment field %s", name) } @@ -1186,6 +1243,13 @@ func (m *CommentMutation) SetField(name string, value ent.Value) error { } m.SetNillableInt(v) return nil + case comment.FieldTable: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTable(v) + return nil } return fmt.Errorf("unknown Comment field %s", name) } @@ -1258,6 +1322,9 @@ func (m *CommentMutation) ClearedFields() []string { if m.FieldCleared(comment.FieldNillableInt) { fields = append(fields, comment.FieldNillableInt) } + if m.FieldCleared(comment.FieldTable) { + fields = append(fields, comment.FieldTable) + } return fields } @@ -1275,6 +1342,9 @@ func (m *CommentMutation) ClearField(name string) error { case comment.FieldNillableInt: m.ClearNillableInt() return nil + case comment.FieldTable: + m.ClearTable() + return nil } return fmt.Errorf("unknown Comment nullable field %s", name) } @@ -1292,6 +1362,9 @@ func (m *CommentMutation) ResetField(name string) error { case comment.FieldNillableInt: m.ResetNillableInt() return nil + case comment.FieldTable: + m.ResetTable() + return nil } return fmt.Errorf("unknown Comment field %s", name) } diff --git a/entc/integration/ent/schema/comment.go b/entc/integration/ent/schema/comment.go index 6c44d0fd18..fc176af8ca 100644 --- a/entc/integration/ent/schema/comment.go +++ b/entc/integration/ent/schema/comment.go @@ -24,5 +24,7 @@ func (Comment) Fields() []ent.Field { field.Int("nillable_int"). Optional(). Nillable(), + field.String("table"). + Optional(), } } diff --git a/entc/integration/gremlin/ent/comment.go b/entc/integration/gremlin/ent/comment.go index f1f86012d7..6aec019334 100644 --- a/entc/integration/gremlin/ent/comment.go +++ b/entc/integration/gremlin/ent/comment.go @@ -24,6 +24,8 @@ type Comment struct { UniqueFloat float64 `json:"unique_float,omitempty"` // NillableInt holds the value of the "nillable_int" field. NillableInt *int `json:"nillable_int,omitempty"` + // Table holds the value of the "table" field. + Table string `json:"table,omitempty"` } // FromResponse scans the gremlin response data into Comment. @@ -37,6 +39,7 @@ func (c *Comment) FromResponse(res *gremlin.Response) error { UniqueInt int `json:"unique_int,omitempty"` UniqueFloat float64 `json:"unique_float,omitempty"` NillableInt *int `json:"nillable_int,omitempty"` + Table string `json:"table,omitempty"` } if err := vmap.Decode(&scanc); err != nil { return err @@ -45,6 +48,7 @@ func (c *Comment) FromResponse(res *gremlin.Response) error { c.UniqueInt = scanc.UniqueInt c.UniqueFloat = scanc.UniqueFloat c.NillableInt = scanc.NillableInt + c.Table = scanc.Table return nil } @@ -79,6 +83,8 @@ func (c *Comment) String() string { builder.WriteString(", nillable_int=") builder.WriteString(fmt.Sprintf("%v", *v)) } + builder.WriteString(", table=") + builder.WriteString(c.Table) builder.WriteByte(')') return builder.String() } @@ -97,6 +103,7 @@ func (c *Comments) FromResponse(res *gremlin.Response) error { UniqueInt int `json:"unique_int,omitempty"` UniqueFloat float64 `json:"unique_float,omitempty"` NillableInt *int `json:"nillable_int,omitempty"` + Table string `json:"table,omitempty"` } if err := vmap.Decode(&scanc); err != nil { return err @@ -107,6 +114,7 @@ func (c *Comments) FromResponse(res *gremlin.Response) error { UniqueInt: v.UniqueInt, UniqueFloat: v.UniqueFloat, NillableInt: v.NillableInt, + Table: v.Table, }) } return nil diff --git a/entc/integration/gremlin/ent/comment/comment.go b/entc/integration/gremlin/ent/comment/comment.go index 2f941c6d26..6d52df3763 100644 --- a/entc/integration/gremlin/ent/comment/comment.go +++ b/entc/integration/gremlin/ent/comment/comment.go @@ -17,6 +17,8 @@ const ( FieldUniqueFloat = "unique_float" // FieldNillableInt holds the string denoting the nillable_int field in the database. FieldNillableInt = "nillable_int" + // FieldTable holds the string denoting the table field in the database. + FieldTable = "table" ) // comment from another template. diff --git a/entc/integration/gremlin/ent/comment/where.go b/entc/integration/gremlin/ent/comment/where.go index 56517b0349..290be33052 100644 --- a/entc/integration/gremlin/ent/comment/where.go +++ b/entc/integration/gremlin/ent/comment/where.go @@ -311,6 +311,105 @@ func NillableIntNotNil() predicate.Comment { }) } +// TableEQ applies the EQ predicate on the "table" field. +func TableEQ(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.EQ(v)) + }) +} + +// TableNEQ applies the NEQ predicate on the "table" field. +func TableNEQ(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.NEQ(v)) + }) +} + +// TableIn applies the In predicate on the "table" field. +func TableIn(vs ...string) predicate.Comment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.Within(v...)) + }) +} + +// TableNotIn applies the NotIn predicate on the "table" field. +func TableNotIn(vs ...string) predicate.Comment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.Without(v...)) + }) +} + +// TableGT applies the GT predicate on the "table" field. +func TableGT(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.GT(v)) + }) +} + +// TableGTE applies the GTE predicate on the "table" field. +func TableGTE(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.GTE(v)) + }) +} + +// TableLT applies the LT predicate on the "table" field. +func TableLT(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.LT(v)) + }) +} + +// TableLTE applies the LTE predicate on the "table" field. +func TableLTE(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.LTE(v)) + }) +} + +// TableContains applies the Contains predicate on the "table" field. +func TableContains(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.Containing(v)) + }) +} + +// TableHasPrefix applies the HasPrefix predicate on the "table" field. +func TableHasPrefix(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.StartingWith(v)) + }) +} + +// TableHasSuffix applies the HasSuffix predicate on the "table" field. +func TableHasSuffix(v string) predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.Has(Label, FieldTable, p.EndingWith(v)) + }) +} + +// TableIsNil applies the IsNil predicate on the "table" field. +func TableIsNil() predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.HasLabel(Label).HasNot(FieldTable) + }) +} + +// TableNotNil applies the NotNil predicate on the "table" field. +func TableNotNil() predicate.Comment { + return predicate.Comment(func(t *dsl.Traversal) { + t.HasLabel(Label).Has(FieldTable) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Comment) predicate.Comment { return predicate.Comment(func(tr *dsl.Traversal) { diff --git a/entc/integration/gremlin/ent/comment_create.go b/entc/integration/gremlin/ent/comment_create.go index 46d6812eca..f09d52e38e 100644 --- a/entc/integration/gremlin/ent/comment_create.go +++ b/entc/integration/gremlin/ent/comment_create.go @@ -52,6 +52,20 @@ func (cc *CommentCreate) SetNillableNillableInt(i *int) *CommentCreate { return cc } +// SetTable sets the "table" field. +func (cc *CommentCreate) SetTable(s string) *CommentCreate { + cc.mutation.SetTable(s) + return cc +} + +// SetNillableTable sets the "table" field if the given value is not nil. +func (cc *CommentCreate) SetNillableTable(s *string) *CommentCreate { + if s != nil { + cc.SetTable(*s) + } + return cc +} + // Mutation returns the CommentMutation object of the builder. func (cc *CommentCreate) Mutation() *CommentMutation { return cc.mutation @@ -171,6 +185,9 @@ func (cc *CommentCreate) gremlin() *dsl.Traversal { if value, ok := cc.mutation.NillableInt(); ok { v.Property(dsl.Single, comment.FieldNillableInt, value) } + if value, ok := cc.mutation.Table(); ok { + v.Property(dsl.Single, comment.FieldTable, value) + } if len(constraints) == 0 { return v.ValueMap(true) } diff --git a/entc/integration/gremlin/ent/comment_update.go b/entc/integration/gremlin/ent/comment_update.go index 125ed29fb0..8e24b19681 100644 --- a/entc/integration/gremlin/ent/comment_update.go +++ b/entc/integration/gremlin/ent/comment_update.go @@ -86,6 +86,26 @@ func (cu *CommentUpdate) ClearNillableInt() *CommentUpdate { return cu } +// SetTable sets the "table" field. +func (cu *CommentUpdate) SetTable(s string) *CommentUpdate { + cu.mutation.SetTable(s) + return cu +} + +// SetNillableTable sets the "table" field if the given value is not nil. +func (cu *CommentUpdate) SetNillableTable(s *string) *CommentUpdate { + if s != nil { + cu.SetTable(*s) + } + return cu +} + +// ClearTable clears the value of the "table" field. +func (cu *CommentUpdate) ClearTable() *CommentUpdate { + cu.mutation.ClearTable() + return cu +} + // Mutation returns the CommentMutation object of the builder. func (cu *CommentUpdate) Mutation() *CommentMutation { return cu.mutation @@ -209,10 +229,16 @@ func (cu *CommentUpdate) gremlin() *dsl.Traversal { if value, ok := cu.mutation.AddedNillableInt(); ok { v.Property(dsl.Single, comment.FieldNillableInt, __.Union(__.Values(comment.FieldNillableInt), __.Constant(value)).Sum()) } + if value, ok := cu.mutation.Table(); ok { + v.Property(dsl.Single, comment.FieldTable, value) + } var properties []interface{} if cu.mutation.NillableIntCleared() { properties = append(properties, comment.FieldNillableInt) } + if cu.mutation.TableCleared() { + properties = append(properties, comment.FieldTable) + } if len(properties) > 0 { v.SideEffect(__.Properties(properties...).Drop()) } @@ -292,6 +318,26 @@ func (cuo *CommentUpdateOne) ClearNillableInt() *CommentUpdateOne { return cuo } +// SetTable sets the "table" field. +func (cuo *CommentUpdateOne) SetTable(s string) *CommentUpdateOne { + cuo.mutation.SetTable(s) + return cuo +} + +// SetNillableTable sets the "table" field if the given value is not nil. +func (cuo *CommentUpdateOne) SetNillableTable(s *string) *CommentUpdateOne { + if s != nil { + cuo.SetTable(*s) + } + return cuo +} + +// ClearTable clears the value of the "table" field. +func (cuo *CommentUpdateOne) ClearTable() *CommentUpdateOne { + cuo.mutation.ClearTable() + return cuo +} + // Mutation returns the CommentMutation object of the builder. func (cuo *CommentUpdateOne) Mutation() *CommentMutation { return cuo.mutation @@ -427,10 +473,16 @@ func (cuo *CommentUpdateOne) gremlin(id string) *dsl.Traversal { if value, ok := cuo.mutation.AddedNillableInt(); ok { v.Property(dsl.Single, comment.FieldNillableInt, __.Union(__.Values(comment.FieldNillableInt), __.Constant(value)).Sum()) } + if value, ok := cuo.mutation.Table(); ok { + v.Property(dsl.Single, comment.FieldTable, value) + } var properties []interface{} if cuo.mutation.NillableIntCleared() { properties = append(properties, comment.FieldNillableInt) } + if cuo.mutation.TableCleared() { + properties = append(properties, comment.FieldTable) + } if len(properties) > 0 { v.SideEffect(__.Properties(properties...).Drop()) } diff --git a/entc/integration/gremlin/ent/mutation.go b/entc/integration/gremlin/ent/mutation.go index df81975929..5a57e00ebf 100644 --- a/entc/integration/gremlin/ent/mutation.go +++ b/entc/integration/gremlin/ent/mutation.go @@ -812,6 +812,7 @@ type CommentMutation struct { addunique_float *float64 nillable_int *int addnillable_int *int + table *string clearedFields map[string]struct{} done bool oldValue func(context.Context) (*Comment, error) @@ -1098,6 +1099,55 @@ func (m *CommentMutation) ResetNillableInt() { delete(m.clearedFields, comment.FieldNillableInt) } +// SetTable sets the "table" field. +func (m *CommentMutation) SetTable(s string) { + m.table = &s +} + +// Table returns the value of the "table" field in the mutation. +func (m *CommentMutation) Table() (r string, exists bool) { + v := m.table + if v == nil { + return + } + return *v, true +} + +// OldTable returns the old "table" field's value of the Comment entity. +// If the Comment object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CommentMutation) OldTable(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTable is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTable requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTable: %w", err) + } + return oldValue.Table, nil +} + +// ClearTable clears the value of the "table" field. +func (m *CommentMutation) ClearTable() { + m.table = nil + m.clearedFields[comment.FieldTable] = struct{}{} +} + +// TableCleared returns if the "table" field was cleared in this mutation. +func (m *CommentMutation) TableCleared() bool { + _, ok := m.clearedFields[comment.FieldTable] + return ok +} + +// ResetTable resets all changes to the "table" field. +func (m *CommentMutation) ResetTable() { + m.table = nil + delete(m.clearedFields, comment.FieldTable) +} + // Where appends a list predicates to the CommentMutation builder. func (m *CommentMutation) Where(ps ...predicate.Comment) { m.predicates = append(m.predicates, ps...) @@ -1117,7 +1167,7 @@ func (m *CommentMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *CommentMutation) Fields() []string { - fields := make([]string, 0, 3) + fields := make([]string, 0, 4) if m.unique_int != nil { fields = append(fields, comment.FieldUniqueInt) } @@ -1127,6 +1177,9 @@ func (m *CommentMutation) Fields() []string { if m.nillable_int != nil { fields = append(fields, comment.FieldNillableInt) } + if m.table != nil { + fields = append(fields, comment.FieldTable) + } return fields } @@ -1141,6 +1194,8 @@ func (m *CommentMutation) Field(name string) (ent.Value, bool) { return m.UniqueFloat() case comment.FieldNillableInt: return m.NillableInt() + case comment.FieldTable: + return m.Table() } return nil, false } @@ -1156,6 +1211,8 @@ func (m *CommentMutation) OldField(ctx context.Context, name string) (ent.Value, return m.OldUniqueFloat(ctx) case comment.FieldNillableInt: return m.OldNillableInt(ctx) + case comment.FieldTable: + return m.OldTable(ctx) } return nil, fmt.Errorf("unknown Comment field %s", name) } @@ -1186,6 +1243,13 @@ func (m *CommentMutation) SetField(name string, value ent.Value) error { } m.SetNillableInt(v) return nil + case comment.FieldTable: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTable(v) + return nil } return fmt.Errorf("unknown Comment field %s", name) } @@ -1258,6 +1322,9 @@ func (m *CommentMutation) ClearedFields() []string { if m.FieldCleared(comment.FieldNillableInt) { fields = append(fields, comment.FieldNillableInt) } + if m.FieldCleared(comment.FieldTable) { + fields = append(fields, comment.FieldTable) + } return fields } @@ -1275,6 +1342,9 @@ func (m *CommentMutation) ClearField(name string) error { case comment.FieldNillableInt: m.ClearNillableInt() return nil + case comment.FieldTable: + m.ClearTable() + return nil } return fmt.Errorf("unknown Comment nullable field %s", name) } @@ -1292,6 +1362,9 @@ func (m *CommentMutation) ResetField(name string) error { case comment.FieldNillableInt: m.ResetNillableInt() return nil + case comment.FieldTable: + m.ResetTable() + return nil } return fmt.Errorf("unknown Comment field %s", name) } From 47fda435010206b99091c2d5fac365c5c920104c Mon Sep 17 00:00:00 2001 From: Jannik C Date: Wed, 20 Apr 2022 13:30:28 +0200 Subject: [PATCH 2/4] doc/md: document reserved schema name --- doc/md/schema-def.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/md/schema-def.md b/doc/md/schema-def.md index 3e281c70d7..66b4eac98c 100755 --- a/doc/md/schema-def.md +++ b/doc/md/schema-def.md @@ -58,6 +58,11 @@ the root directory of your project, and can be generated by `entc` as follows: go run entgo.io/ent/cmd/ent init User Group ``` +:::note +Pleae note, that `Client` is a reserved Go struct and cannot be used as schema name. For database tables +named `client`, please use an annotation as mentioned [here](schema-annotations.md#custom-table-name). +::: + ## It's Just Another ORM If you are used to the definition of relations over edges, that's fine. From e81e70e04ca67b37fa20b87bd8fafecb40788909 Mon Sep 17 00:00:00 2001 From: Jannik C Date: Wed, 20 Apr 2022 15:14:51 +0200 Subject: [PATCH 3/4] doc/md: revert reserved schema name as this was already working --- entc/gen/graph.go | 16 ++-------------- entc/gen/graph_test.go | 3 --- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/entc/gen/graph.go b/entc/gen/graph.go index 35a5368814..e20e683a72 100644 --- a/entc/gen/graph.go +++ b/entc/gen/graph.go @@ -142,9 +142,8 @@ func (f GenerateFunc) Generate(g *Graph) error { func NewGraph(c *Config, schemas ...*load.Schema) (g *Graph, err error) { defer catch(&err) g = &Graph{c, make([]*Type, 0, len(schemas)), schemas} - for _, s := range schemas { - check(reservedName(s.Name), "add schema %q", s.Name) - g.addNode(s) + for i := range schemas { + g.addNode(schemas[i]) } for i := range schemas { g.addEdges(schemas[i]) @@ -439,17 +438,6 @@ func resolve(t *Type) error { return nil } -var reservedNames = []string{"Client"} - -func reservedName(n string) error { - for _, rn := range reservedNames { - if rn == n { - return fmt.Errorf("%q is a reserved name and cannot be used as schema name", n) - } - } - return nil -} - // Tables returns the schema definitions of SQL tables for the graph. func (g *Graph) Tables() (all []*schema.Table, err error) { tables := make(map[string]*schema.Table) diff --git a/entc/gen/graph_test.go b/entc/gen/graph_test.go index 3287cae9bb..61bea6c4a3 100644 --- a/entc/gen/graph_test.go +++ b/entc/gen/graph_test.go @@ -130,9 +130,6 @@ func TestNewGraph(t *testing.T) { require.Equal(t2.Edges[5], t2.Edges[6].Ref) require.Equal(map[string]string{"Name": "From"}, t2.Edges[5].Annotations["GQL"]) require.Equal(map[string]string{"Name": "To"}, t2.Edges[6].Annotations["GQL"]) - - _, err = NewGraph(&Config{Package: "entc/gen", Storage: drivers[0]}, &load.Schema{Name: "Client"}) - require.EqualError(err, `entc/gen: add schema "Client": "Client" is a reserved name and cannot be used as schema name`) } func TestNewGraphRequiredLoop(t *testing.T) { From 80a982b5f40ce388fce9ba50af3e7f0ac05786e7 Mon Sep 17 00:00:00 2001 From: Jannik C Date: Wed, 20 Apr 2022 16:18:33 +0200 Subject: [PATCH 4/4] doc/md: rephrase --- doc/md/schema-def.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/md/schema-def.md b/doc/md/schema-def.md index 66b4eac98c..7865a7053d 100755 --- a/doc/md/schema-def.md +++ b/doc/md/schema-def.md @@ -59,8 +59,9 @@ go run entgo.io/ent/cmd/ent init User Group ``` :::note -Pleae note, that `Client` is a reserved Go struct and cannot be used as schema name. For database tables -named `client`, please use an annotation as mentioned [here](schema-annotations.md#custom-table-name). +Please note, that some schema names (like `Client`) are not available due to +[internal use](https://pkg.go.dev/entgo.io/ent/entc/gen#ValidSchemaName). You can circumvent reserved names by using an +annotation as mentioned [here](schema-annotations.md#custom-table-name). ::: ## It's Just Another ORM