From 2e36c6569a53ca9d82a3d90bbb13e69db9b51319 Mon Sep 17 00:00:00 2001
From: Ariel Mashraki <7413593+a8m@users.noreply.github.com>
Date: Mon, 28 Mar 2022 12:54:39 +0300
Subject: [PATCH] dialect/sql/schema: prefix sqlite unique indexes with table
name (#2433)
Fixed https://github.com/ent/ent/issues/2421
---
dialect/sql/schema/sqlite.go | 6 +-
entc/integration/migrate/entv2/car.go | 14 +-
entc/integration/migrate/entv2/car/car.go | 3 +
entc/integration/migrate/entv2/car/where.go | 132 +++++++++++++
entc/integration/migrate/entv2/car_create.go | 22 +++
entc/integration/migrate/entv2/car_query.go | 24 +++
entc/integration/migrate/entv2/car_update.go | 66 +++++++
.../migrate/entv2/migrate/schema.go | 6 +-
entc/integration/migrate/entv2/mutation.go | 176 +++++++++++++++++-
entc/integration/migrate/entv2/pet.go | 14 +-
entc/integration/migrate/entv2/pet/pet.go | 3 +
entc/integration/migrate/entv2/pet/where.go | 132 +++++++++++++
entc/integration/migrate/entv2/pet_create.go | 22 +++
entc/integration/migrate/entv2/pet_query.go | 24 +++
entc/integration/migrate/entv2/pet_update.go | 66 +++++++
entc/integration/migrate/entv2/schema/user.go | 16 ++
16 files changed, 715 insertions(+), 11 deletions(-)
diff --git a/dialect/sql/schema/sqlite.go b/dialect/sql/schema/sqlite.go
index 2881a75f85..ce46631bd4 100644
--- a/dialect/sql/schema/sqlite.go
+++ b/dialect/sql/schema/sqlite.go
@@ -408,15 +408,15 @@ func (d *SQLite) atTypeC(c1 *Column, c2 *schema.Column) error {
func (d *SQLite) atUniqueC(t1 *Table, c1 *Column, t2 *schema.Table, c2 *schema.Column) {
// For UNIQUE columns, SQLite create an implicit index named
- // "sqlite_autoindex_
_". Ent uses the MySQL approach
- // in its migration, and name these indexes as the columns.
+ // "sqlite_autoindex__". Ent uses the PostgreSQL approach
+ // in its migration, and name these indexes as "__key".
for _, idx := range t1.Indexes {
// Index also defined explicitly, and will be add in atIndexes.
if idx.Unique && d.atImplicitIndexName(idx, t1, c1) {
return
}
}
- t2.AddIndexes(schema.NewUniqueIndex(c1.Name).AddColumns(c2))
+ t2.AddIndexes(schema.NewUniqueIndex(fmt.Sprintf("%s_%s_key", t2.Name, c1.Name)).AddColumns(c2))
}
func (d *SQLite) atImplicitIndexName(idx *Index, t1 *Table, c1 *Column) bool {
diff --git a/entc/integration/migrate/entv2/car.go b/entc/integration/migrate/entv2/car.go
index a8c549ceec..d34c482161 100644
--- a/entc/integration/migrate/entv2/car.go
+++ b/entc/integration/migrate/entv2/car.go
@@ -17,9 +17,11 @@ import (
// Car is the model entity for the Car schema.
type Car struct {
- config
+ config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
+ // Name holds the value of the "name" field.
+ Name string `json:"name,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the CarQuery when eager-loading is set.
Edges CarEdges `json:"edges"`
@@ -56,6 +58,8 @@ func (*Car) scanValues(columns []string) ([]interface{}, error) {
switch columns[i] {
case car.FieldID:
values[i] = new(sql.NullInt64)
+ case car.FieldName:
+ values[i] = new(sql.NullString)
case car.ForeignKeys[0]: // user_car
values[i] = new(sql.NullInt64)
default:
@@ -79,6 +83,12 @@ func (c *Car) assignValues(columns []string, values []interface{}) error {
return fmt.Errorf("unexpected type %T for field id", value)
}
c.ID = int(value.Int64)
+ case car.FieldName:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field name", values[i])
+ } else if value.Valid {
+ c.Name = value.String
+ }
case car.ForeignKeys[0]:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for edge-field user_car", value)
@@ -119,6 +129,8 @@ func (c *Car) String() string {
var builder strings.Builder
builder.WriteString("Car(")
builder.WriteString(fmt.Sprintf("id=%v", c.ID))
+ builder.WriteString(", name=")
+ builder.WriteString(c.Name)
builder.WriteByte(')')
return builder.String()
}
diff --git a/entc/integration/migrate/entv2/car/car.go b/entc/integration/migrate/entv2/car/car.go
index e2dcfe8cbc..a6c9dbb350 100644
--- a/entc/integration/migrate/entv2/car/car.go
+++ b/entc/integration/migrate/entv2/car/car.go
@@ -11,6 +11,8 @@ const (
Label = "car"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
+ // FieldName holds the string denoting the name field in the database.
+ FieldName = "name"
// EdgeOwner holds the string denoting the owner edge name in mutations.
EdgeOwner = "owner"
// UserFieldID holds the string denoting the ID field of the User.
@@ -29,6 +31,7 @@ const (
// Columns holds all SQL columns for car fields.
var Columns = []string{
FieldID,
+ FieldName,
}
// ForeignKeys holds the SQL foreign-keys that are owned by the "Car"
diff --git a/entc/integration/migrate/entv2/car/where.go b/entc/integration/migrate/entv2/car/where.go
index 8831e6ce91..d7b7ea96cd 100644
--- a/entc/integration/migrate/entv2/car/where.go
+++ b/entc/integration/migrate/entv2/car/where.go
@@ -95,6 +95,138 @@ func IDLTE(id int) predicate.Car {
})
}
+// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
+func Name(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.EQ(s.C(FieldName), v))
+ })
+}
+
+// NameEQ applies the EQ predicate on the "name" field.
+func NameEQ(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.EQ(s.C(FieldName), v))
+ })
+}
+
+// NameNEQ applies the NEQ predicate on the "name" field.
+func NameNEQ(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.NEQ(s.C(FieldName), v))
+ })
+}
+
+// NameIn applies the In predicate on the "name" field.
+func NameIn(vs ...string) predicate.Car {
+ v := make([]interface{}, len(vs))
+ for i := range v {
+ v[i] = vs[i]
+ }
+ return predicate.Car(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(FieldName), v...))
+ })
+}
+
+// NameNotIn applies the NotIn predicate on the "name" field.
+func NameNotIn(vs ...string) predicate.Car {
+ v := make([]interface{}, len(vs))
+ for i := range v {
+ v[i] = vs[i]
+ }
+ return predicate.Car(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(FieldName), v...))
+ })
+}
+
+// NameGT applies the GT predicate on the "name" field.
+func NameGT(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.GT(s.C(FieldName), v))
+ })
+}
+
+// NameGTE applies the GTE predicate on the "name" field.
+func NameGTE(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.GTE(s.C(FieldName), v))
+ })
+}
+
+// NameLT applies the LT predicate on the "name" field.
+func NameLT(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.LT(s.C(FieldName), v))
+ })
+}
+
+// NameLTE applies the LTE predicate on the "name" field.
+func NameLTE(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.LTE(s.C(FieldName), v))
+ })
+}
+
+// NameContains applies the Contains predicate on the "name" field.
+func NameContains(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.Contains(s.C(FieldName), v))
+ })
+}
+
+// NameHasPrefix applies the HasPrefix predicate on the "name" field.
+func NameHasPrefix(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.HasPrefix(s.C(FieldName), v))
+ })
+}
+
+// NameHasSuffix applies the HasSuffix predicate on the "name" field.
+func NameHasSuffix(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.HasSuffix(s.C(FieldName), v))
+ })
+}
+
+// NameIsNil applies the IsNil predicate on the "name" field.
+func NameIsNil() predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.IsNull(s.C(FieldName)))
+ })
+}
+
+// NameNotNil applies the NotNil predicate on the "name" field.
+func NameNotNil() predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.NotNull(s.C(FieldName)))
+ })
+}
+
+// NameEqualFold applies the EqualFold predicate on the "name" field.
+func NameEqualFold(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.EqualFold(s.C(FieldName), v))
+ })
+}
+
+// NameContainsFold applies the ContainsFold predicate on the "name" field.
+func NameContainsFold(v string) predicate.Car {
+ return predicate.Car(func(s *sql.Selector) {
+ s.Where(sql.ContainsFold(s.C(FieldName), v))
+ })
+}
+
// HasOwner applies the HasEdge predicate on the "owner" edge.
func HasOwner() predicate.Car {
return predicate.Car(func(s *sql.Selector) {
diff --git a/entc/integration/migrate/entv2/car_create.go b/entc/integration/migrate/entv2/car_create.go
index 7f8dc04d53..fd14b2f2e4 100644
--- a/entc/integration/migrate/entv2/car_create.go
+++ b/entc/integration/migrate/entv2/car_create.go
@@ -24,6 +24,20 @@ type CarCreate struct {
hooks []Hook
}
+// SetName sets the "name" field.
+func (cc *CarCreate) SetName(s string) *CarCreate {
+ cc.mutation.SetName(s)
+ return cc
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (cc *CarCreate) SetNillableName(s *string) *CarCreate {
+ if s != nil {
+ cc.SetName(*s)
+ }
+ return cc
+}
+
// SetOwnerID sets the "owner" edge to the User entity by ID.
func (cc *CarCreate) SetOwnerID(id int) *CarCreate {
cc.mutation.SetOwnerID(id)
@@ -135,6 +149,14 @@ func (cc *CarCreate) createSpec() (*Car, *sqlgraph.CreateSpec) {
},
}
)
+ if value, ok := cc.mutation.Name(); ok {
+ _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Value: value,
+ Column: car.FieldName,
+ })
+ _node.Name = value
+ }
if nodes := cc.mutation.OwnerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
diff --git a/entc/integration/migrate/entv2/car_query.go b/entc/integration/migrate/entv2/car_query.go
index dae4e7be12..70dc4abbf3 100644
--- a/entc/integration/migrate/entv2/car_query.go
+++ b/entc/integration/migrate/entv2/car_query.go
@@ -291,6 +291,19 @@ func (cq *CarQuery) WithOwner(opts ...func(*UserQuery)) *CarQuery {
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// Name string `json:"name,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.Car.Query().
+// GroupBy(car.FieldName).
+// Aggregate(entv2.Count()).
+// Scan(ctx, &v)
+//
func (cq *CarQuery) GroupBy(field string, fields ...string) *CarGroupBy {
grbuild := &CarGroupBy{config: cq.config}
grbuild.fields = append([]string{field}, fields...)
@@ -307,6 +320,17 @@ func (cq *CarQuery) GroupBy(field string, fields ...string) *CarGroupBy {
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// Name string `json:"name,omitempty"`
+// }
+//
+// client.Car.Query().
+// Select(car.FieldName).
+// Scan(ctx, &v)
+//
func (cq *CarQuery) Select(fields ...string) *CarSelect {
cq.fields = append(cq.fields, fields...)
selbuild := &CarSelect{CarQuery: cq}
diff --git a/entc/integration/migrate/entv2/car_update.go b/entc/integration/migrate/entv2/car_update.go
index 8156e20a79..538af98443 100644
--- a/entc/integration/migrate/entv2/car_update.go
+++ b/entc/integration/migrate/entv2/car_update.go
@@ -32,6 +32,26 @@ func (cu *CarUpdate) Where(ps ...predicate.Car) *CarUpdate {
return cu
}
+// SetName sets the "name" field.
+func (cu *CarUpdate) SetName(s string) *CarUpdate {
+ cu.mutation.SetName(s)
+ return cu
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (cu *CarUpdate) SetNillableName(s *string) *CarUpdate {
+ if s != nil {
+ cu.SetName(*s)
+ }
+ return cu
+}
+
+// ClearName clears the value of the "name" field.
+func (cu *CarUpdate) ClearName() *CarUpdate {
+ cu.mutation.ClearName()
+ return cu
+}
+
// SetOwnerID sets the "owner" edge to the User entity by ID.
func (cu *CarUpdate) SetOwnerID(id int) *CarUpdate {
cu.mutation.SetOwnerID(id)
@@ -140,6 +160,19 @@ func (cu *CarUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
}
}
+ if value, ok := cu.mutation.Name(); ok {
+ _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Value: value,
+ Column: car.FieldName,
+ })
+ }
+ if cu.mutation.NameCleared() {
+ _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Column: car.FieldName,
+ })
+ }
if cu.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@@ -194,6 +227,26 @@ type CarUpdateOne struct {
mutation *CarMutation
}
+// SetName sets the "name" field.
+func (cuo *CarUpdateOne) SetName(s string) *CarUpdateOne {
+ cuo.mutation.SetName(s)
+ return cuo
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (cuo *CarUpdateOne) SetNillableName(s *string) *CarUpdateOne {
+ if s != nil {
+ cuo.SetName(*s)
+ }
+ return cuo
+}
+
+// ClearName clears the value of the "name" field.
+func (cuo *CarUpdateOne) ClearName() *CarUpdateOne {
+ cuo.mutation.ClearName()
+ return cuo
+}
+
// SetOwnerID sets the "owner" edge to the User entity by ID.
func (cuo *CarUpdateOne) SetOwnerID(id int) *CarUpdateOne {
cuo.mutation.SetOwnerID(id)
@@ -326,6 +379,19 @@ func (cuo *CarUpdateOne) sqlSave(ctx context.Context) (_node *Car, err error) {
}
}
}
+ if value, ok := cuo.mutation.Name(); ok {
+ _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Value: value,
+ Column: car.FieldName,
+ })
+ }
+ if cuo.mutation.NameCleared() {
+ _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Column: car.FieldName,
+ })
+ }
if cuo.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
diff --git a/entc/integration/migrate/entv2/migrate/schema.go b/entc/integration/migrate/entv2/migrate/schema.go
index e49628fecb..5d349c257a 100644
--- a/entc/integration/migrate/entv2/migrate/schema.go
+++ b/entc/integration/migrate/entv2/migrate/schema.go
@@ -16,6 +16,7 @@ var (
// CarColumns holds the columns for the "Car" table.
CarColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "name", Type: field.TypeString, Unique: true, Nullable: true},
{Name: "user_car", Type: field.TypeInt},
}
// CarTable holds the schema information for the "Car" table.
@@ -26,7 +27,7 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "Car_users_car",
- Columns: []*schema.Column{CarColumns[1]},
+ Columns: []*schema.Column{CarColumns[2]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
@@ -108,6 +109,7 @@ var (
// PetsColumns holds the columns for the "pets" table.
PetsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "name", Type: field.TypeString, Unique: true, Nullable: true},
{Name: "owner_id", Type: field.TypeInt, Unique: true, Nullable: true},
}
// PetsTable holds the schema information for the "pets" table.
@@ -118,7 +120,7 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "user_pet_id",
- Columns: []*schema.Column{PetsColumns[1]},
+ Columns: []*schema.Column{PetsColumns[2]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.SetNull,
},
diff --git a/entc/integration/migrate/entv2/mutation.go b/entc/integration/migrate/entv2/mutation.go
index 455727e139..abf3e9092b 100644
--- a/entc/integration/migrate/entv2/mutation.go
+++ b/entc/integration/migrate/entv2/mutation.go
@@ -48,6 +48,7 @@ type CarMutation struct {
op Op
typ string
id *int
+ name *string
clearedFields map[string]struct{}
owner *int
clearedowner bool
@@ -154,6 +155,55 @@ func (m *CarMutation) IDs(ctx context.Context) ([]int, error) {
}
}
+// SetName sets the "name" field.
+func (m *CarMutation) SetName(s string) {
+ m.name = &s
+}
+
+// Name returns the value of the "name" field in the mutation.
+func (m *CarMutation) Name() (r string, exists bool) {
+ v := m.name
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldName returns the old "name" field's value of the Car entity.
+// If the Car 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 *CarMutation) OldName(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldName is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldName requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldName: %w", err)
+ }
+ return oldValue.Name, nil
+}
+
+// ClearName clears the value of the "name" field.
+func (m *CarMutation) ClearName() {
+ m.name = nil
+ m.clearedFields[car.FieldName] = struct{}{}
+}
+
+// NameCleared returns if the "name" field was cleared in this mutation.
+func (m *CarMutation) NameCleared() bool {
+ _, ok := m.clearedFields[car.FieldName]
+ return ok
+}
+
+// ResetName resets all changes to the "name" field.
+func (m *CarMutation) ResetName() {
+ m.name = nil
+ delete(m.clearedFields, car.FieldName)
+}
+
// SetOwnerID sets the "owner" edge to the User entity by id.
func (m *CarMutation) SetOwnerID(id int) {
m.owner = &id
@@ -212,7 +262,10 @@ func (m *CarMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *CarMutation) Fields() []string {
- fields := make([]string, 0, 0)
+ fields := make([]string, 0, 1)
+ if m.name != nil {
+ fields = append(fields, car.FieldName)
+ }
return fields
}
@@ -220,6 +273,10 @@ func (m *CarMutation) Fields() []string {
// return value indicates that this field was not set, or was not defined in the
// schema.
func (m *CarMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case car.FieldName:
+ return m.Name()
+ }
return nil, false
}
@@ -227,6 +284,10 @@ func (m *CarMutation) Field(name string) (ent.Value, bool) {
// returned if the mutation operation is not UpdateOne, or the query to the
// database failed.
func (m *CarMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case car.FieldName:
+ return m.OldName(ctx)
+ }
return nil, fmt.Errorf("unknown Car field %s", name)
}
@@ -235,6 +296,13 @@ func (m *CarMutation) OldField(ctx context.Context, name string) (ent.Value, err
// type.
func (m *CarMutation) SetField(name string, value ent.Value) error {
switch name {
+ case car.FieldName:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetName(v)
+ return nil
}
return fmt.Errorf("unknown Car field %s", name)
}
@@ -256,13 +324,19 @@ func (m *CarMutation) AddedField(name string) (ent.Value, bool) {
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *CarMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ }
return fmt.Errorf("unknown Car numeric field %s", name)
}
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *CarMutation) ClearedFields() []string {
- return nil
+ var fields []string
+ if m.FieldCleared(car.FieldName) {
+ fields = append(fields, car.FieldName)
+ }
+ return fields
}
// FieldCleared returns a boolean indicating if a field with the given name was
@@ -275,12 +349,22 @@ func (m *CarMutation) FieldCleared(name string) bool {
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *CarMutation) ClearField(name string) error {
+ switch name {
+ case car.FieldName:
+ m.ClearName()
+ return nil
+ }
return fmt.Errorf("unknown Car nullable field %s", name)
}
// ResetField resets all changes in the mutation for the field with the given name.
// It returns an error if the field is not defined in the schema.
func (m *CarMutation) ResetField(name string) error {
+ switch name {
+ case car.FieldName:
+ m.ResetName()
+ return nil
+ }
return fmt.Errorf("unknown Car field %s", name)
}
@@ -2344,6 +2428,7 @@ type PetMutation struct {
op Op
typ string
id *int
+ name *string
clearedFields map[string]struct{}
owner *int
clearedowner bool
@@ -2450,6 +2535,55 @@ func (m *PetMutation) IDs(ctx context.Context) ([]int, error) {
}
}
+// SetName sets the "name" field.
+func (m *PetMutation) SetName(s string) {
+ m.name = &s
+}
+
+// Name returns the value of the "name" field in the mutation.
+func (m *PetMutation) Name() (r string, exists bool) {
+ v := m.name
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldName returns the old "name" field's value of the Pet entity.
+// If the Pet 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 *PetMutation) OldName(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldName is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldName requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldName: %w", err)
+ }
+ return oldValue.Name, nil
+}
+
+// ClearName clears the value of the "name" field.
+func (m *PetMutation) ClearName() {
+ m.name = nil
+ m.clearedFields[pet.FieldName] = struct{}{}
+}
+
+// NameCleared returns if the "name" field was cleared in this mutation.
+func (m *PetMutation) NameCleared() bool {
+ _, ok := m.clearedFields[pet.FieldName]
+ return ok
+}
+
+// ResetName resets all changes to the "name" field.
+func (m *PetMutation) ResetName() {
+ m.name = nil
+ delete(m.clearedFields, pet.FieldName)
+}
+
// SetOwnerID sets the "owner" edge to the User entity by id.
func (m *PetMutation) SetOwnerID(id int) {
m.owner = &id
@@ -2508,7 +2642,10 @@ func (m *PetMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *PetMutation) Fields() []string {
- fields := make([]string, 0, 0)
+ fields := make([]string, 0, 1)
+ if m.name != nil {
+ fields = append(fields, pet.FieldName)
+ }
return fields
}
@@ -2516,6 +2653,10 @@ func (m *PetMutation) Fields() []string {
// return value indicates that this field was not set, or was not defined in the
// schema.
func (m *PetMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case pet.FieldName:
+ return m.Name()
+ }
return nil, false
}
@@ -2523,6 +2664,10 @@ func (m *PetMutation) Field(name string) (ent.Value, bool) {
// returned if the mutation operation is not UpdateOne, or the query to the
// database failed.
func (m *PetMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case pet.FieldName:
+ return m.OldName(ctx)
+ }
return nil, fmt.Errorf("unknown Pet field %s", name)
}
@@ -2531,6 +2676,13 @@ func (m *PetMutation) OldField(ctx context.Context, name string) (ent.Value, err
// type.
func (m *PetMutation) SetField(name string, value ent.Value) error {
switch name {
+ case pet.FieldName:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetName(v)
+ return nil
}
return fmt.Errorf("unknown Pet field %s", name)
}
@@ -2552,13 +2704,19 @@ func (m *PetMutation) AddedField(name string) (ent.Value, bool) {
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *PetMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ }
return fmt.Errorf("unknown Pet numeric field %s", name)
}
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *PetMutation) ClearedFields() []string {
- return nil
+ var fields []string
+ if m.FieldCleared(pet.FieldName) {
+ fields = append(fields, pet.FieldName)
+ }
+ return fields
}
// FieldCleared returns a boolean indicating if a field with the given name was
@@ -2571,12 +2729,22 @@ func (m *PetMutation) FieldCleared(name string) bool {
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *PetMutation) ClearField(name string) error {
+ switch name {
+ case pet.FieldName:
+ m.ClearName()
+ return nil
+ }
return fmt.Errorf("unknown Pet nullable field %s", name)
}
// ResetField resets all changes in the mutation for the field with the given name.
// It returns an error if the field is not defined in the schema.
func (m *PetMutation) ResetField(name string) error {
+ switch name {
+ case pet.FieldName:
+ m.ResetName()
+ return nil
+ }
return fmt.Errorf("unknown Pet field %s", name)
}
diff --git a/entc/integration/migrate/entv2/pet.go b/entc/integration/migrate/entv2/pet.go
index 51b0378dc7..7269625f39 100644
--- a/entc/integration/migrate/entv2/pet.go
+++ b/entc/integration/migrate/entv2/pet.go
@@ -17,9 +17,11 @@ import (
// Pet is the model entity for the Pet schema.
type Pet struct {
- config
+ config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
+ // Name holds the value of the "name" field.
+ Name string `json:"name,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the PetQuery when eager-loading is set.
Edges PetEdges `json:"edges"`
@@ -56,6 +58,8 @@ func (*Pet) scanValues(columns []string) ([]interface{}, error) {
switch columns[i] {
case pet.FieldID:
values[i] = new(sql.NullInt64)
+ case pet.FieldName:
+ values[i] = new(sql.NullString)
case pet.ForeignKeys[0]: // owner_id
values[i] = new(sql.NullInt64)
default:
@@ -79,6 +83,12 @@ func (pe *Pet) assignValues(columns []string, values []interface{}) error {
return fmt.Errorf("unexpected type %T for field id", value)
}
pe.ID = int(value.Int64)
+ case pet.FieldName:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field name", values[i])
+ } else if value.Valid {
+ pe.Name = value.String
+ }
case pet.ForeignKeys[0]:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for edge-field owner_id", value)
@@ -119,6 +129,8 @@ func (pe *Pet) String() string {
var builder strings.Builder
builder.WriteString("Pet(")
builder.WriteString(fmt.Sprintf("id=%v", pe.ID))
+ builder.WriteString(", name=")
+ builder.WriteString(pe.Name)
builder.WriteByte(')')
return builder.String()
}
diff --git a/entc/integration/migrate/entv2/pet/pet.go b/entc/integration/migrate/entv2/pet/pet.go
index d24b211967..b0c9ef76a2 100644
--- a/entc/integration/migrate/entv2/pet/pet.go
+++ b/entc/integration/migrate/entv2/pet/pet.go
@@ -11,6 +11,8 @@ const (
Label = "pet"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
+ // FieldName holds the string denoting the name field in the database.
+ FieldName = "name"
// EdgeOwner holds the string denoting the owner edge name in mutations.
EdgeOwner = "owner"
// UserFieldID holds the string denoting the ID field of the User.
@@ -29,6 +31,7 @@ const (
// Columns holds all SQL columns for pet fields.
var Columns = []string{
FieldID,
+ FieldName,
}
// ForeignKeys holds the SQL foreign-keys that are owned by the "pets"
diff --git a/entc/integration/migrate/entv2/pet/where.go b/entc/integration/migrate/entv2/pet/where.go
index c9bae23641..f28093b7fc 100644
--- a/entc/integration/migrate/entv2/pet/where.go
+++ b/entc/integration/migrate/entv2/pet/where.go
@@ -95,6 +95,138 @@ func IDLTE(id int) predicate.Pet {
})
}
+// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
+func Name(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.EQ(s.C(FieldName), v))
+ })
+}
+
+// NameEQ applies the EQ predicate on the "name" field.
+func NameEQ(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.EQ(s.C(FieldName), v))
+ })
+}
+
+// NameNEQ applies the NEQ predicate on the "name" field.
+func NameNEQ(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.NEQ(s.C(FieldName), v))
+ })
+}
+
+// NameIn applies the In predicate on the "name" field.
+func NameIn(vs ...string) predicate.Pet {
+ v := make([]interface{}, len(vs))
+ for i := range v {
+ v[i] = vs[i]
+ }
+ return predicate.Pet(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(FieldName), v...))
+ })
+}
+
+// NameNotIn applies the NotIn predicate on the "name" field.
+func NameNotIn(vs ...string) predicate.Pet {
+ v := make([]interface{}, len(vs))
+ for i := range v {
+ v[i] = vs[i]
+ }
+ return predicate.Pet(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(FieldName), v...))
+ })
+}
+
+// NameGT applies the GT predicate on the "name" field.
+func NameGT(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.GT(s.C(FieldName), v))
+ })
+}
+
+// NameGTE applies the GTE predicate on the "name" field.
+func NameGTE(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.GTE(s.C(FieldName), v))
+ })
+}
+
+// NameLT applies the LT predicate on the "name" field.
+func NameLT(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.LT(s.C(FieldName), v))
+ })
+}
+
+// NameLTE applies the LTE predicate on the "name" field.
+func NameLTE(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.LTE(s.C(FieldName), v))
+ })
+}
+
+// NameContains applies the Contains predicate on the "name" field.
+func NameContains(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.Contains(s.C(FieldName), v))
+ })
+}
+
+// NameHasPrefix applies the HasPrefix predicate on the "name" field.
+func NameHasPrefix(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.HasPrefix(s.C(FieldName), v))
+ })
+}
+
+// NameHasSuffix applies the HasSuffix predicate on the "name" field.
+func NameHasSuffix(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.HasSuffix(s.C(FieldName), v))
+ })
+}
+
+// NameIsNil applies the IsNil predicate on the "name" field.
+func NameIsNil() predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.IsNull(s.C(FieldName)))
+ })
+}
+
+// NameNotNil applies the NotNil predicate on the "name" field.
+func NameNotNil() predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.NotNull(s.C(FieldName)))
+ })
+}
+
+// NameEqualFold applies the EqualFold predicate on the "name" field.
+func NameEqualFold(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.EqualFold(s.C(FieldName), v))
+ })
+}
+
+// NameContainsFold applies the ContainsFold predicate on the "name" field.
+func NameContainsFold(v string) predicate.Pet {
+ return predicate.Pet(func(s *sql.Selector) {
+ s.Where(sql.ContainsFold(s.C(FieldName), v))
+ })
+}
+
// HasOwner applies the HasEdge predicate on the "owner" edge.
func HasOwner() predicate.Pet {
return predicate.Pet(func(s *sql.Selector) {
diff --git a/entc/integration/migrate/entv2/pet_create.go b/entc/integration/migrate/entv2/pet_create.go
index 9a06f85308..95f86a5a58 100644
--- a/entc/integration/migrate/entv2/pet_create.go
+++ b/entc/integration/migrate/entv2/pet_create.go
@@ -23,6 +23,20 @@ type PetCreate struct {
hooks []Hook
}
+// SetName sets the "name" field.
+func (pc *PetCreate) SetName(s string) *PetCreate {
+ pc.mutation.SetName(s)
+ return pc
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (pc *PetCreate) SetNillableName(s *string) *PetCreate {
+ if s != nil {
+ pc.SetName(*s)
+ }
+ return pc
+}
+
// SetOwnerID sets the "owner" edge to the User entity by ID.
func (pc *PetCreate) SetOwnerID(id int) *PetCreate {
pc.mutation.SetOwnerID(id)
@@ -139,6 +153,14 @@ func (pc *PetCreate) createSpec() (*Pet, *sqlgraph.CreateSpec) {
},
}
)
+ if value, ok := pc.mutation.Name(); ok {
+ _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Value: value,
+ Column: pet.FieldName,
+ })
+ _node.Name = value
+ }
if nodes := pc.mutation.OwnerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2O,
diff --git a/entc/integration/migrate/entv2/pet_query.go b/entc/integration/migrate/entv2/pet_query.go
index 7f198ce3ad..c6801d5cc1 100644
--- a/entc/integration/migrate/entv2/pet_query.go
+++ b/entc/integration/migrate/entv2/pet_query.go
@@ -291,6 +291,19 @@ func (pq *PetQuery) WithOwner(opts ...func(*UserQuery)) *PetQuery {
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// Name string `json:"name,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.Pet.Query().
+// GroupBy(pet.FieldName).
+// Aggregate(entv2.Count()).
+// Scan(ctx, &v)
+//
func (pq *PetQuery) GroupBy(field string, fields ...string) *PetGroupBy {
grbuild := &PetGroupBy{config: pq.config}
grbuild.fields = append([]string{field}, fields...)
@@ -307,6 +320,17 @@ func (pq *PetQuery) GroupBy(field string, fields ...string) *PetGroupBy {
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// Name string `json:"name,omitempty"`
+// }
+//
+// client.Pet.Query().
+// Select(pet.FieldName).
+// Scan(ctx, &v)
+//
func (pq *PetQuery) Select(fields ...string) *PetSelect {
pq.fields = append(pq.fields, fields...)
selbuild := &PetSelect{PetQuery: pq}
diff --git a/entc/integration/migrate/entv2/pet_update.go b/entc/integration/migrate/entv2/pet_update.go
index 86e5f2a1fd..7fcb9cbc50 100644
--- a/entc/integration/migrate/entv2/pet_update.go
+++ b/entc/integration/migrate/entv2/pet_update.go
@@ -32,6 +32,26 @@ func (pu *PetUpdate) Where(ps ...predicate.Pet) *PetUpdate {
return pu
}
+// SetName sets the "name" field.
+func (pu *PetUpdate) SetName(s string) *PetUpdate {
+ pu.mutation.SetName(s)
+ return pu
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (pu *PetUpdate) SetNillableName(s *string) *PetUpdate {
+ if s != nil {
+ pu.SetName(*s)
+ }
+ return pu
+}
+
+// ClearName clears the value of the "name" field.
+func (pu *PetUpdate) ClearName() *PetUpdate {
+ pu.mutation.ClearName()
+ return pu
+}
+
// SetOwnerID sets the "owner" edge to the User entity by ID.
func (pu *PetUpdate) SetOwnerID(id int) *PetUpdate {
pu.mutation.SetOwnerID(id)
@@ -134,6 +154,19 @@ func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
}
}
+ if value, ok := pu.mutation.Name(); ok {
+ _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Value: value,
+ Column: pet.FieldName,
+ })
+ }
+ if pu.mutation.NameCleared() {
+ _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Column: pet.FieldName,
+ })
+ }
if pu.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2O,
@@ -188,6 +221,26 @@ type PetUpdateOne struct {
mutation *PetMutation
}
+// SetName sets the "name" field.
+func (puo *PetUpdateOne) SetName(s string) *PetUpdateOne {
+ puo.mutation.SetName(s)
+ return puo
+}
+
+// SetNillableName sets the "name" field if the given value is not nil.
+func (puo *PetUpdateOne) SetNillableName(s *string) *PetUpdateOne {
+ if s != nil {
+ puo.SetName(*s)
+ }
+ return puo
+}
+
+// ClearName clears the value of the "name" field.
+func (puo *PetUpdateOne) ClearName() *PetUpdateOne {
+ puo.mutation.ClearName()
+ return puo
+}
+
// SetOwnerID sets the "owner" edge to the User entity by ID.
func (puo *PetUpdateOne) SetOwnerID(id int) *PetUpdateOne {
puo.mutation.SetOwnerID(id)
@@ -314,6 +367,19 @@ func (puo *PetUpdateOne) sqlSave(ctx context.Context) (_node *Pet, err error) {
}
}
}
+ if value, ok := puo.mutation.Name(); ok {
+ _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Value: value,
+ Column: pet.FieldName,
+ })
+ }
+ if puo.mutation.NameCleared() {
+ _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
+ Type: field.TypeString,
+ Column: pet.FieldName,
+ })
+ }
if puo.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2O,
diff --git a/entc/integration/migrate/entv2/schema/user.go b/entc/integration/migrate/entv2/schema/user.go
index 45186bdc67..08ee012050 100644
--- a/entc/integration/migrate/entv2/schema/user.go
+++ b/entc/integration/migrate/entv2/schema/user.go
@@ -152,6 +152,14 @@ func (Car) Annotations() []schema.Annotation {
}
}
+func (Car) Fields() []ent.Field {
+ return []ent.Field{
+ field.String("name").
+ Optional().
+ Unique(),
+ }
+}
+
func (Car) Edges() []ent.Edge {
return []ent.Edge{
edge.From("owner", User.Type).
@@ -171,6 +179,14 @@ type Pet struct {
ent.Schema
}
+func (Pet) Fields() []ent.Field {
+ return []ent.Field{
+ field.String("name").
+ Optional().
+ Unique(),
+ }
+}
+
func (Pet) Edges() []ent.Edge {
return []ent.Edge{
edge.From("owner", User.Type).