From 59f172f06a60af7f486da2f2cd1af218c166e954 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Wed, 1 Jan 2020 19:12:11 +0200 Subject: [PATCH] entc/integration/migrate: add integration tests for migrate --- entc/integration/migrate/entv1/car.go | 85 +++ entc/integration/migrate/entv1/car/car.go | 29 + entc/integration/migrate/entv1/car/where.go | 174 +++++ entc/integration/migrate/entv1/car_create.go | 103 +++ entc/integration/migrate/entv1/car_delete.go | 86 +++ entc/integration/migrate/entv1/car_query.go | 603 +++++++++++++++++ entc/integration/migrate/entv1/car_update.go | 278 ++++++++ entc/integration/migrate/entv1/client.go | 143 +++- .../integration/migrate/entv1/example_test.go | 70 ++ .../migrate/entv1/migrate/schema.go | 49 +- .../migrate/entv1/predicate/predicate.go | 3 + entc/integration/migrate/entv1/schema/user.go | 25 + entc/integration/migrate/entv1/tx.go | 5 +- entc/integration/migrate/entv1/user.go | 20 + entc/integration/migrate/entv1/user/user.go | 19 + entc/integration/migrate/entv1/user/where.go | 121 ++++ entc/integration/migrate/entv1/user_create.go | 176 +++++ entc/integration/migrate/entv1/user_query.go | 49 ++ entc/integration/migrate/entv1/user_update.go | 622 +++++++++++++++++- entc/integration/migrate/entv2/car.go | 85 +++ entc/integration/migrate/entv2/car/car.go | 29 + entc/integration/migrate/entv2/car/where.go | 174 +++++ entc/integration/migrate/entv2/car_create.go | 103 +++ entc/integration/migrate/entv2/car_delete.go | 86 +++ entc/integration/migrate/entv2/car_query.go | 603 +++++++++++++++++ entc/integration/migrate/entv2/car_update.go | 278 ++++++++ entc/integration/migrate/entv2/client.go | 101 ++- .../integration/migrate/entv2/example_test.go | 33 + .../migrate/entv2/migrate/schema.go | 22 + .../migrate/entv2/predicate/predicate.go | 3 + entc/integration/migrate/entv2/schema/user.go | 22 + entc/integration/migrate/entv2/tx.go | 5 +- entc/integration/migrate/entv2/user.go | 5 + entc/integration/migrate/entv2/user/user.go | 7 + entc/integration/migrate/entv2/user/where.go | 31 + entc/integration/migrate/entv2/user_create.go | 41 ++ entc/integration/migrate/entv2/user_query.go | 13 + entc/integration/migrate/entv2/user_update.go | 161 +++++ entc/integration/migrate/migrate_test.go | 14 +- 39 files changed, 4436 insertions(+), 40 deletions(-) create mode 100644 entc/integration/migrate/entv1/car.go create mode 100644 entc/integration/migrate/entv1/car/car.go create mode 100644 entc/integration/migrate/entv1/car/where.go create mode 100644 entc/integration/migrate/entv1/car_create.go create mode 100644 entc/integration/migrate/entv1/car_delete.go create mode 100644 entc/integration/migrate/entv1/car_query.go create mode 100644 entc/integration/migrate/entv1/car_update.go create mode 100644 entc/integration/migrate/entv2/car.go create mode 100644 entc/integration/migrate/entv2/car/car.go create mode 100644 entc/integration/migrate/entv2/car/where.go create mode 100644 entc/integration/migrate/entv2/car_create.go create mode 100644 entc/integration/migrate/entv2/car_delete.go create mode 100644 entc/integration/migrate/entv2/car_query.go create mode 100644 entc/integration/migrate/entv2/car_update.go diff --git a/entc/integration/migrate/entv1/car.go b/entc/integration/migrate/entv1/car.go new file mode 100644 index 000000000..ebfebe2c6 --- /dev/null +++ b/entc/integration/migrate/entv1/car.go @@ -0,0 +1,85 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv1 + +import ( + "fmt" + "strings" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" +) + +// Car is the model entity for the Car schema. +type Car struct { + config + // ID of the ent. + ID int `json:"id,omitempty"` +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Car) scanValues() []interface{} { + return []interface{}{ + &sql.NullInt64{}, + } +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Car fields. +func (c *Car) assignValues(values ...interface{}) error { + if m, n := len(values), len(car.Columns); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = int(value.Int64) + values = values[1:] + return nil +} + +// QueryOwner queries the owner edge of the Car. +func (c *Car) QueryOwner() *UserQuery { + return (&CarClient{c.config}).QueryOwner(c) +} + +// Update returns a builder for updating this Car. +// Note that, you need to call Car.Unwrap() before calling this method, if this Car +// was returned from a transaction, and the transaction was committed or rolled back. +func (c *Car) Update() *CarUpdateOne { + return (&CarClient{c.config}).UpdateOne(c) +} + +// Unwrap unwraps the entity that was returned from a transaction after it was closed, +// so that all next queries will be executed through the driver which created the transaction. +func (c *Car) Unwrap() *Car { + tx, ok := c.config.driver.(*txDriver) + if !ok { + panic("entv1: Car is not a transactional entity") + } + c.config.driver = tx.drv + return c +} + +// String implements the fmt.Stringer. +func (c *Car) String() string { + var builder strings.Builder + builder.WriteString("Car(") + builder.WriteString(fmt.Sprintf("id=%v", c.ID)) + builder.WriteByte(')') + return builder.String() +} + +// Cars is a parsable slice of Car. +type Cars []*Car + +func (c Cars) config(cfg config) { + for _i := range c { + c[_i].config = cfg + } +} diff --git a/entc/integration/migrate/entv1/car/car.go b/entc/integration/migrate/entv1/car/car.go new file mode 100644 index 000000000..9738845d9 --- /dev/null +++ b/entc/integration/migrate/entv1/car/car.go @@ -0,0 +1,29 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package car + +const ( + // Label holds the string label denoting the car type in the database. + Label = "car" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + + // Table holds the table name of the car in the database. + Table = "cars" + // OwnerTable is the table the holds the owner relation/edge. + OwnerTable = "cars" + // OwnerInverseTable is the table name for the User entity. + // It exists in this package in order to avoid circular dependency with the "user" package. + OwnerInverseTable = "users" + // OwnerColumn is the table column denoting the owner relation/edge. + OwnerColumn = "owner_id" +) + +// Columns holds all SQL columns are car fields. +var Columns = []string{ + FieldID, +} diff --git a/entc/integration/migrate/entv1/car/where.go b/entc/integration/migrate/entv1/car/where.go new file mode 100644 index 000000000..728adeb2d --- /dev/null +++ b/entc/integration/migrate/entv1/car/where.go @@ -0,0 +1,174 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package car + +import ( + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" +) + +// ID filters vertices based on their identifier. +func ID(id int) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }, + ) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }, + ) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }, + ) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Car { + 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(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }, + ) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Car { + 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(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }, + ) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }, + ) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }, + ) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }, + ) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }, + ) +} + +// HasOwner applies the HasEdge predicate on the "owner" edge. +func HasOwner() predicate.Car { + return predicate.Car(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(OwnerTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, OwnerTable, OwnerColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasOwnerWith applies the HasEdge predicate on the "owner" edge with a given conditions (other predicates). +func HasOwnerWith(preds ...predicate.User) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(OwnerInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, OwnerTable, OwnerColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + +// And groups list of predicates with the AND operator between them. +func And(predicates ...predicate.Car) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }, + ) +} + +// Or groups list of predicates with the OR operator between them. +func Or(predicates ...predicate.Car) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }, + ) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Car) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + p(s.Not()) + }, + ) +} diff --git a/entc/integration/migrate/entv1/car_create.go b/entc/integration/migrate/entv1/car_create.go new file mode 100644 index 000000000..6e63680d8 --- /dev/null +++ b/entc/integration/migrate/entv1/car_create.go @@ -0,0 +1,103 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv1 + +import ( + "context" + "errors" + + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" + "github.com/facebookincubator/ent/schema/field" +) + +// CarCreate is the builder for creating a Car entity. +type CarCreate struct { + config + owner map[int]struct{} +} + +// SetOwnerID sets the owner edge to User by id. +func (cc *CarCreate) SetOwnerID(id int) *CarCreate { + if cc.owner == nil { + cc.owner = make(map[int]struct{}) + } + cc.owner[id] = struct{}{} + return cc +} + +// SetNillableOwnerID sets the owner edge to User by id if the given value is not nil. +func (cc *CarCreate) SetNillableOwnerID(id *int) *CarCreate { + if id != nil { + cc = cc.SetOwnerID(*id) + } + return cc +} + +// SetOwner sets the owner edge to User. +func (cc *CarCreate) SetOwner(u *User) *CarCreate { + return cc.SetOwnerID(u.ID) +} + +// Save creates the Car in the database. +func (cc *CarCreate) Save(ctx context.Context) (*Car, error) { + if len(cc.owner) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"owner\"") + } + return cc.sqlSave(ctx) +} + +// SaveX calls Save and panics if Save returns an error. +func (cc *CarCreate) SaveX(ctx context.Context) *Car { + v, err := cc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cc *CarCreate) sqlSave(ctx context.Context) (*Car, error) { + var ( + c = &Car{config: cc.config} + spec = &sqlgraph.CreateSpec{ + Table: car.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + } + ) + if nodes := cc.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } + if err := sqlgraph.CreateNode(ctx, cc.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } + return nil, err + } + id := spec.ID.Value.(int64) + c.ID = int(id) + return c, nil +} diff --git a/entc/integration/migrate/entv1/car_delete.go b/entc/integration/migrate/entv1/car_delete.go new file mode 100644 index 000000000..11184508e --- /dev/null +++ b/entc/integration/migrate/entv1/car_delete.go @@ -0,0 +1,86 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv1 + +import ( + "context" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" + "github.com/facebookincubator/ent/schema/field" +) + +// CarDelete is the builder for deleting a Car entity. +type CarDelete struct { + config + predicates []predicate.Car +} + +// Where adds a new predicate to the delete builder. +func (cd *CarDelete) Where(ps ...predicate.Car) *CarDelete { + cd.predicates = append(cd.predicates, ps...) + return cd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (cd *CarDelete) Exec(ctx context.Context) (int, error) { + return cd.sqlExec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (cd *CarDelete) ExecX(ctx context.Context) int { + n, err := cd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (cd *CarDelete) sqlExec(ctx context.Context) (int, error) { + spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + if ps := cd.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, cd.driver, spec) +} + +// CarDeleteOne is the builder for deleting a single Car entity. +type CarDeleteOne struct { + cd *CarDelete +} + +// Exec executes the deletion query. +func (cdo *CarDeleteOne) Exec(ctx context.Context) error { + n, err := cdo.cd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &ErrNotFound{car.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (cdo *CarDeleteOne) ExecX(ctx context.Context) { + cdo.cd.ExecX(ctx) +} diff --git a/entc/integration/migrate/entv1/car_query.go b/entc/integration/migrate/entv1/car_query.go new file mode 100644 index 000000000..932a0a95c --- /dev/null +++ b/entc/integration/migrate/entv1/car_query.go @@ -0,0 +1,603 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv1 + +import ( + "context" + "errors" + "fmt" + "math" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" + "github.com/facebookincubator/ent/schema/field" +) + +// CarQuery is the builder for querying Car entities. +type CarQuery struct { + config + limit *int + offset *int + order []Order + unique []string + predicates []predicate.Car + // intermediate query. + sql *sql.Selector +} + +// Where adds a new predicate for the builder. +func (cq *CarQuery) Where(ps ...predicate.Car) *CarQuery { + cq.predicates = append(cq.predicates, ps...) + return cq +} + +// Limit adds a limit step to the query. +func (cq *CarQuery) Limit(limit int) *CarQuery { + cq.limit = &limit + return cq +} + +// Offset adds an offset step to the query. +func (cq *CarQuery) Offset(offset int) *CarQuery { + cq.offset = &offset + return cq +} + +// Order adds an order step to the query. +func (cq *CarQuery) Order(o ...Order) *CarQuery { + cq.order = append(cq.order, o...) + return cq +} + +// QueryOwner chains the current query on the owner edge. +func (cq *CarQuery) QueryOwner() *UserQuery { + query := &UserQuery{config: cq.config} + step := sqlgraph.NewStep( + sqlgraph.From(car.Table, car.FieldID, cq.sqlQuery()), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, car.OwnerTable, car.OwnerColumn), + ) + query.sql = sqlgraph.SetNeighbors(cq.driver.Dialect(), step) + return query +} + +// First returns the first Car entity in the query. Returns *ErrNotFound when no car was found. +func (cq *CarQuery) First(ctx context.Context) (*Car, error) { + cs, err := cq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(cs) == 0 { + return nil, &ErrNotFound{car.Label} + } + return cs[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (cq *CarQuery) FirstX(ctx context.Context) *Car { + c, err := cq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return c +} + +// FirstID returns the first Car id in the query. Returns *ErrNotFound when no id was found. +func (cq *CarQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = cq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &ErrNotFound{car.Label} + return + } + return ids[0], nil +} + +// FirstXID is like FirstID, but panics if an error occurs. +func (cq *CarQuery) FirstXID(ctx context.Context) int { + id, err := cq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns the only Car entity in the query, returns an error if not exactly one entity was returned. +func (cq *CarQuery) Only(ctx context.Context) (*Car, error) { + cs, err := cq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(cs) { + case 1: + return cs[0], nil + case 0: + return nil, &ErrNotFound{car.Label} + default: + return nil, &ErrNotSingular{car.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (cq *CarQuery) OnlyX(ctx context.Context) *Car { + c, err := cq.Only(ctx) + if err != nil { + panic(err) + } + return c +} + +// OnlyID returns the only Car id in the query, returns an error if not exactly one id was returned. +func (cq *CarQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = cq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &ErrNotFound{car.Label} + default: + err = &ErrNotSingular{car.Label} + } + return +} + +// OnlyXID is like OnlyID, but panics if an error occurs. +func (cq *CarQuery) OnlyXID(ctx context.Context) int { + id, err := cq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Cars. +func (cq *CarQuery) All(ctx context.Context) ([]*Car, error) { + return cq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (cq *CarQuery) AllX(ctx context.Context) []*Car { + cs, err := cq.All(ctx) + if err != nil { + panic(err) + } + return cs +} + +// IDs executes the query and returns a list of Car ids. +func (cq *CarQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := cq.Select(car.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (cq *CarQuery) IDsX(ctx context.Context) []int { + ids, err := cq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (cq *CarQuery) Count(ctx context.Context) (int, error) { + return cq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (cq *CarQuery) CountX(ctx context.Context) int { + count, err := cq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (cq *CarQuery) Exist(ctx context.Context) (bool, error) { + return cq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (cq *CarQuery) ExistX(ctx context.Context) bool { + exist, err := cq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the query builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (cq *CarQuery) Clone() *CarQuery { + return &CarQuery{ + config: cq.config, + limit: cq.limit, + offset: cq.offset, + order: append([]Order{}, cq.order...), + unique: append([]string{}, cq.unique...), + predicates: append([]predicate.Car{}, cq.predicates...), + // clone intermediate query. + sql: cq.sql.Clone(), + } +} + +// GroupBy used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +func (cq *CarQuery) GroupBy(field string, fields ...string) *CarGroupBy { + group := &CarGroupBy{config: cq.config} + group.fields = append([]string{field}, fields...) + group.sql = cq.sqlQuery() + return group +} + +// Select one or more fields from the given query. +func (cq *CarQuery) Select(field string, fields ...string) *CarSelect { + selector := &CarSelect{config: cq.config} + selector.fields = append([]string{field}, fields...) + selector.sql = cq.sqlQuery() + return selector +} + +func (cq *CarQuery) sqlAll(ctx context.Context) ([]*Car, error) { + var ( + nodes []*Car + spec = cq.querySpec() + ) + spec.ScanValues = func() []interface{} { + node := &Car{config: cq.config} + nodes = append(nodes, node) + return node.scanValues() + } + spec.Assign = func(values ...interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("entv1: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + return node.assignValues(values...) + } + if err := sqlgraph.QueryNodes(ctx, cq.driver, spec); err != nil { + return nil, err + } + return nodes, nil +} + +func (cq *CarQuery) sqlCount(ctx context.Context) (int, error) { + spec := cq.querySpec() + return sqlgraph.CountNodes(ctx, cq.driver, spec) +} + +func (cq *CarQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := cq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("entv1: check existence: %v", err) + } + return n > 0, nil +} + +func (cq *CarQuery) querySpec() *sqlgraph.QuerySpec { + spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + From: cq.sql, + Unique: true, + } + if ps := cq.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := cq.limit; limit != nil { + spec.Limit = *limit + } + if offset := cq.offset; offset != nil { + spec.Offset = *offset + } + if ps := cq.order; len(ps) > 0 { + spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return spec +} + +func (cq *CarQuery) sqlQuery() *sql.Selector { + builder := sql.Dialect(cq.driver.Dialect()) + t1 := builder.Table(car.Table) + selector := builder.Select(t1.Columns(car.Columns...)...).From(t1) + if cq.sql != nil { + selector = cq.sql + selector.Select(selector.Columns(car.Columns...)...) + } + for _, p := range cq.predicates { + p(selector) + } + for _, p := range cq.order { + p(selector) + } + if offset := cq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := cq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// CarGroupBy is the builder for group-by Car entities. +type CarGroupBy struct { + config + fields []string + fns []Aggregate + // intermediate query. + sql *sql.Selector +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (cgb *CarGroupBy) Aggregate(fns ...Aggregate) *CarGroupBy { + cgb.fns = append(cgb.fns, fns...) + return cgb +} + +// Scan applies the group-by query and scan the result into the given value. +func (cgb *CarGroupBy) Scan(ctx context.Context, v interface{}) error { + return cgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (cgb *CarGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := cgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv1: CarGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (cgb *CarGroupBy) StringsX(ctx context.Context) []string { + v, err := cgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv1: CarGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (cgb *CarGroupBy) IntsX(ctx context.Context) []int { + v, err := cgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv1: CarGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (cgb *CarGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := cgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv1: CarGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (cgb *CarGroupBy) BoolsX(ctx context.Context) []bool { + v, err := cgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cgb *CarGroupBy) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := cgb.sqlQuery().Query() + if err := cgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (cgb *CarGroupBy) sqlQuery() *sql.Selector { + selector := cgb.sql + columns := make([]string, 0, len(cgb.fields)+len(cgb.fns)) + columns = append(columns, cgb.fields...) + for _, fn := range cgb.fns { + columns = append(columns, fn(selector)) + } + return selector.Select(columns...).GroupBy(cgb.fields...) +} + +// CarSelect is the builder for select fields of Car entities. +type CarSelect struct { + config + fields []string + // intermediate queries. + sql *sql.Selector +} + +// Scan applies the selector query and scan the result into the given value. +func (cs *CarSelect) Scan(ctx context.Context, v interface{}) error { + return cs.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (cs *CarSelect) ScanX(ctx context.Context, v interface{}) { + if err := cs.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Strings(ctx context.Context) ([]string, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv1: CarSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (cs *CarSelect) StringsX(ctx context.Context) []string { + v, err := cs.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Ints(ctx context.Context) ([]int, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv1: CarSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (cs *CarSelect) IntsX(ctx context.Context) []int { + v, err := cs.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv1: CarSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (cs *CarSelect) Float64sX(ctx context.Context) []float64 { + v, err := cs.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Bools(ctx context.Context) ([]bool, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv1: CarSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (cs *CarSelect) BoolsX(ctx context.Context) []bool { + v, err := cs.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cs *CarSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := cs.sqlQuery().Query() + if err := cs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (cs *CarSelect) sqlQuery() sql.Querier { + selector := cs.sql + selector.Select(selector.Columns(cs.fields...)...) + return selector +} diff --git a/entc/integration/migrate/entv1/car_update.go b/entc/integration/migrate/entv1/car_update.go new file mode 100644 index 000000000..103addde3 --- /dev/null +++ b/entc/integration/migrate/entv1/car_update.go @@ -0,0 +1,278 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv1 + +import ( + "context" + "errors" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" + "github.com/facebookincubator/ent/schema/field" +) + +// CarUpdate is the builder for updating Car entities. +type CarUpdate struct { + config + owner map[int]struct{} + clearedOwner bool + predicates []predicate.Car +} + +// Where adds a new predicate for the builder. +func (cu *CarUpdate) Where(ps ...predicate.Car) *CarUpdate { + cu.predicates = append(cu.predicates, ps...) + return cu +} + +// SetOwnerID sets the owner edge to User by id. +func (cu *CarUpdate) SetOwnerID(id int) *CarUpdate { + if cu.owner == nil { + cu.owner = make(map[int]struct{}) + } + cu.owner[id] = struct{}{} + return cu +} + +// SetNillableOwnerID sets the owner edge to User by id if the given value is not nil. +func (cu *CarUpdate) SetNillableOwnerID(id *int) *CarUpdate { + if id != nil { + cu = cu.SetOwnerID(*id) + } + return cu +} + +// SetOwner sets the owner edge to User. +func (cu *CarUpdate) SetOwner(u *User) *CarUpdate { + return cu.SetOwnerID(u.ID) +} + +// ClearOwner clears the owner edge to User. +func (cu *CarUpdate) ClearOwner() *CarUpdate { + cu.clearedOwner = true + return cu +} + +// Save executes the query and returns the number of rows/vertices matched by this operation. +func (cu *CarUpdate) Save(ctx context.Context) (int, error) { + if len(cu.owner) > 1 { + return 0, errors.New("entv1: multiple assignments on a unique edge \"owner\"") + } + return cu.sqlSave(ctx) +} + +// SaveX is like Save, but panics if an error occurs. +func (cu *CarUpdate) SaveX(ctx context.Context) int { + affected, err := cu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (cu *CarUpdate) Exec(ctx context.Context) error { + _, err := cu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cu *CarUpdate) ExecX(ctx context.Context) { + if err := cu.Exec(ctx); err != nil { + panic(err) + } +} + +func (cu *CarUpdate) sqlSave(ctx context.Context) (n int, err error) { + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if cu.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := cu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.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, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } + return 0, err + } + return n, nil +} + +// CarUpdateOne is the builder for updating a single Car entity. +type CarUpdateOne struct { + config + id int + owner map[int]struct{} + clearedOwner bool +} + +// SetOwnerID sets the owner edge to User by id. +func (cuo *CarUpdateOne) SetOwnerID(id int) *CarUpdateOne { + if cuo.owner == nil { + cuo.owner = make(map[int]struct{}) + } + cuo.owner[id] = struct{}{} + return cuo +} + +// SetNillableOwnerID sets the owner edge to User by id if the given value is not nil. +func (cuo *CarUpdateOne) SetNillableOwnerID(id *int) *CarUpdateOne { + if id != nil { + cuo = cuo.SetOwnerID(*id) + } + return cuo +} + +// SetOwner sets the owner edge to User. +func (cuo *CarUpdateOne) SetOwner(u *User) *CarUpdateOne { + return cuo.SetOwnerID(u.ID) +} + +// ClearOwner clears the owner edge to User. +func (cuo *CarUpdateOne) ClearOwner() *CarUpdateOne { + cuo.clearedOwner = true + return cuo +} + +// Save executes the query and returns the updated entity. +func (cuo *CarUpdateOne) Save(ctx context.Context) (*Car, error) { + if len(cuo.owner) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"owner\"") + } + return cuo.sqlSave(ctx) +} + +// SaveX is like Save, but panics if an error occurs. +func (cuo *CarUpdateOne) SaveX(ctx context.Context) *Car { + c, err := cuo.Save(ctx) + if err != nil { + panic(err) + } + return c +} + +// Exec executes the query on the entity. +func (cuo *CarUpdateOne) Exec(ctx context.Context) error { + _, err := cuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cuo *CarUpdateOne) ExecX(ctx context.Context) { + if err := cuo.Exec(ctx); err != nil { + panic(err) + } +} + +func (cuo *CarUpdateOne) sqlSave(ctx context.Context) (c *Car, err error) { + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + if cuo.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := cuo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + c = &Car{config: cuo.config} + spec.Assign = c.assignValues + spec.ScanValues = c.scanValues() + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } + return nil, err + } + return c, nil +} diff --git a/entc/integration/migrate/entv1/client.go b/entc/integration/migrate/entv1/client.go index 922a27d62..dce1af90c 100644 --- a/entc/integration/migrate/entv1/client.go +++ b/entc/integration/migrate/entv1/client.go @@ -13,10 +13,12 @@ import ( "github.com/facebookincubator/ent/entc/integration/migrate/entv1/migrate" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" "github.com/facebookincubator/ent/dialect" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" ) // Client is the client that holds all ent builders. @@ -24,6 +26,8 @@ type Client struct { config // Schema is the client for creating, migrating and dropping schema. Schema *migrate.Schema + // Car is the client for interacting with the Car builders. + Car *CarClient // User is the client for interacting with the User builders. User *UserClient } @@ -35,6 +39,7 @@ func NewClient(opts ...Option) *Client { return &Client{ config: c, Schema: migrate.NewSchema(c.driver), + Car: NewCarClient(c), User: NewUserClient(c), } } @@ -67,6 +72,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := config{driver: tx, log: c.log, debug: c.debug} return &Tx{ config: cfg, + Car: NewCarClient(cfg), User: NewUserClient(cfg), }, nil } @@ -74,7 +80,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { // Debug returns a new debug-client. It's used to get verbose logging on specific operations. // // client.Debug(). -// User. +// Car. // Query(). // Count(ctx) // @@ -86,6 +92,7 @@ func (c *Client) Debug() *Client { return &Client{ config: cfg, Schema: migrate.NewSchema(cfg.driver), + Car: NewCarClient(cfg), User: NewUserClient(cfg), } } @@ -95,6 +102,84 @@ func (c *Client) Close() error { return c.driver.Close() } +// CarClient is a client for the Car schema. +type CarClient struct { + config +} + +// NewCarClient returns a client for the Car from the given config. +func NewCarClient(c config) *CarClient { + return &CarClient{config: c} +} + +// Create returns a create builder for Car. +func (c *CarClient) Create() *CarCreate { + return &CarCreate{config: c.config} +} + +// Update returns an update builder for Car. +func (c *CarClient) Update() *CarUpdate { + return &CarUpdate{config: c.config} +} + +// UpdateOne returns an update builder for the given entity. +func (c *CarClient) UpdateOne(ca *Car) *CarUpdateOne { + return c.UpdateOneID(ca.ID) +} + +// UpdateOneID returns an update builder for the given id. +func (c *CarClient) UpdateOneID(id int) *CarUpdateOne { + return &CarUpdateOne{config: c.config, id: id} +} + +// Delete returns a delete builder for Car. +func (c *CarClient) Delete() *CarDelete { + return &CarDelete{config: c.config} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *CarClient) DeleteOne(ca *Car) *CarDeleteOne { + return c.DeleteOneID(ca.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *CarClient) DeleteOneID(id int) *CarDeleteOne { + return &CarDeleteOne{c.Delete().Where(car.ID(id))} +} + +// Create returns a query builder for Car. +func (c *CarClient) Query() *CarQuery { + return &CarQuery{config: c.config} +} + +// Get returns a Car entity by its id. +func (c *CarClient) Get(ctx context.Context, id int) (*Car, error) { + return c.Query().Where(car.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *CarClient) GetX(ctx context.Context, id int) *Car { + ca, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return ca +} + +// QueryOwner queries the owner edge of a Car. +func (c *CarClient) QueryOwner(ca *Car) *UserQuery { + query := &UserQuery{config: c.config} + id := ca.ID + step := sqlgraph.NewStep( + sqlgraph.From(car.Table, car.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, car.OwnerTable, car.OwnerColumn), + ) + query.sql = sqlgraph.Neighbors(ca.driver.Dialect(), step) + + return query +} + // UserClient is a client for the User schema. type UserClient struct { config @@ -158,3 +243,59 @@ func (c *UserClient) GetX(ctx context.Context, id int) *User { } return u } + +// QueryParent queries the parent edge of a User. +func (c *UserClient) QueryParent(u *User) *UserQuery { + query := &UserQuery{config: c.config} + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, user.ParentTable, user.ParentColumn), + ) + query.sql = sqlgraph.Neighbors(u.driver.Dialect(), step) + + return query +} + +// QueryChildren queries the children edge of a User. +func (c *UserClient) QueryChildren(u *User) *UserQuery { + query := &UserQuery{config: c.config} + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, user.ChildrenTable, user.ChildrenColumn), + ) + query.sql = sqlgraph.Neighbors(u.driver.Dialect(), step) + + return query +} + +// QuerySpouse queries the spouse edge of a User. +func (c *UserClient) QuerySpouse(u *User) *UserQuery { + query := &UserQuery{config: c.config} + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, user.SpouseTable, user.SpouseColumn), + ) + query.sql = sqlgraph.Neighbors(u.driver.Dialect(), step) + + return query +} + +// QueryCar queries the car edge of a User. +func (c *UserClient) QueryCar(u *User) *CarQuery { + query := &CarQuery{config: c.config} + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(car.Table, car.FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, user.CarTable, user.CarColumn), + ) + query.sql = sqlgraph.Neighbors(u.driver.Dialect(), step) + + return query +} diff --git a/entc/integration/migrate/entv1/example_test.go b/entc/integration/migrate/entv1/example_test.go index b246b88b5..9e1400c6f 100644 --- a/entc/integration/migrate/entv1/example_test.go +++ b/entc/integration/migrate/entv1/example_test.go @@ -21,6 +21,29 @@ import ( // var dsn string +func ExampleCar() { + if dsn == "" { + return + } + ctx := context.Background() + drv, err := sql.Open("mysql", dsn) + if err != nil { + log.Fatalf("failed creating database client: %v", err) + } + defer drv.Close() + client := NewClient(Driver(drv)) + // creating vertices for the car's edges. + + // create car vertex with its edges. + c := client.Car. + Create(). + SaveX(ctx) + log.Println("car created:", c) + + // query edges. + + // Output: +} func ExampleUser() { if dsn == "" { return @@ -33,6 +56,32 @@ func ExampleUser() { defer drv.Close() client := NewClient(Driver(drv)) // creating vertices for the user's edges. + u1 := client.User. + Create(). + SetAge(1). + SetName("string"). + SetNickname("string"). + SetAddress("string"). + SetRenamed("string"). + SetBlob(nil). + SetState(user.StateLoggedIn). + SaveX(ctx) + log.Println("user created:", u1) + u2 := client.User. + Create(). + SetAge(1). + SetName("string"). + SetNickname("string"). + SetAddress("string"). + SetRenamed("string"). + SetBlob(nil). + SetState(user.StateLoggedIn). + SaveX(ctx) + log.Println("user created:", u2) + c3 := client.Car. + Create(). + SaveX(ctx) + log.Println("car created:", c3) // create user vertex with its edges. u := client.User. @@ -44,10 +93,31 @@ func ExampleUser() { SetRenamed("string"). SetBlob(nil). SetState(user.StateLoggedIn). + AddChildren(u1). + SetSpouse(u2). + SetCar(c3). SaveX(ctx) log.Println("user created:", u) // query edges. + u1, err = u.QueryChildren().First(ctx) + if err != nil { + log.Fatalf("failed querying children: %v", err) + } + log.Println("children found:", u1) + + u2, err = u.QuerySpouse().First(ctx) + if err != nil { + log.Fatalf("failed querying spouse: %v", err) + } + log.Println("spouse found:", u2) + + c3, err = u.QueryCar().First(ctx) + if err != nil { + log.Fatalf("failed querying car: %v", err) + } + log.Println("car found:", c3) + // Output: } diff --git a/entc/integration/migrate/entv1/migrate/schema.go b/entc/integration/migrate/entv1/migrate/schema.go index 22110d04f..2f0d69086 100644 --- a/entc/integration/migrate/entv1/migrate/schema.go +++ b/entc/integration/migrate/entv1/migrate/schema.go @@ -12,6 +12,26 @@ import ( ) var ( + // CarsColumns holds the columns for the "cars" table. + CarsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "owner_id", Type: field.TypeInt, Unique: true, Nullable: true}, + } + // CarsTable holds the schema information for the "cars" table. + CarsTable = &schema.Table{ + Name: "cars", + Columns: CarsColumns, + PrimaryKey: []*schema.Column{CarsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "cars_users_car", + Columns: []*schema.Column{CarsColumns[1]}, + + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.SetNull, + }, + }, + } // UsersColumns holds the columns for the "users" table. UsersColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -22,13 +42,30 @@ var ( {Name: "renamed", Type: field.TypeString, Nullable: true}, {Name: "blob", Type: field.TypeBytes, Nullable: true, Size: 255}, {Name: "state", Type: field.TypeEnum, Nullable: true, Enums: []string{"logged_in", "logged_out"}}, + {Name: "parent_id", Type: field.TypeInt, Nullable: true}, + {Name: "user_spouse_id", Type: field.TypeInt, Unique: true, Nullable: true}, } // UsersTable holds the schema information for the "users" table. UsersTable = &schema.Table{ - Name: "users", - Columns: UsersColumns, - PrimaryKey: []*schema.Column{UsersColumns[0]}, - ForeignKeys: []*schema.ForeignKey{}, + Name: "users", + Columns: UsersColumns, + PrimaryKey: []*schema.Column{UsersColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "users_users_children", + Columns: []*schema.Column{UsersColumns[8]}, + + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.SetNull, + }, + { + Symbol: "users_users_spouse", + Columns: []*schema.Column{UsersColumns[9]}, + + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.SetNull, + }, + }, Indexes: []*schema.Index{ { Name: "user_name_address", @@ -39,9 +76,13 @@ var ( } // Tables holds all the tables in the schema. Tables = []*schema.Table{ + CarsTable, UsersTable, } ) func init() { + CarsTable.ForeignKeys[0].RefTable = UsersTable + UsersTable.ForeignKeys[0].RefTable = UsersTable + UsersTable.ForeignKeys[1].RefTable = UsersTable } diff --git a/entc/integration/migrate/entv1/predicate/predicate.go b/entc/integration/migrate/entv1/predicate/predicate.go index 0af459cef..c94c842e7 100644 --- a/entc/integration/migrate/entv1/predicate/predicate.go +++ b/entc/integration/migrate/entv1/predicate/predicate.go @@ -10,5 +10,8 @@ import ( "github.com/facebookincubator/ent/dialect/sql" ) +// Car is the predicate function for car builders. +type Car func(*sql.Selector) + // User is the predicate function for user builders. type User func(*sql.Selector) diff --git a/entc/integration/migrate/entv1/schema/user.go b/entc/integration/migrate/entv1/schema/user.go index 058b0f3fb..7fcdf0d7e 100644 --- a/entc/integration/migrate/entv1/schema/user.go +++ b/entc/integration/migrate/entv1/schema/user.go @@ -6,6 +6,7 @@ package schema import ( "github.com/facebookincubator/ent" + "github.com/facebookincubator/ent/schema/edge" "github.com/facebookincubator/ent/schema/field" "github.com/facebookincubator/ent/schema/index" ) @@ -36,9 +37,33 @@ func (User) Fields() []ent.Field { } } +func (User) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("children", User.Type). + From("parent"). + Unique(), + edge.To("spouse", User.Type). + Unique(), + edge.To("car", Car.Type). + Unique(), + } +} + func (User) Indexes() []ent.Index { return []ent.Index{ index.Fields("name", "address"). Unique(), } } + +type Car struct { + ent.Schema +} + +func (Car) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("owner", User.Type). + Ref("car"). + Unique(), + } +} diff --git a/entc/integration/migrate/entv1/tx.go b/entc/integration/migrate/entv1/tx.go index cd0ad4566..d91fe7fc5 100644 --- a/entc/integration/migrate/entv1/tx.go +++ b/entc/integration/migrate/entv1/tx.go @@ -16,6 +16,8 @@ import ( // Tx is a transactional client that is created by calling Client.Tx(). type Tx struct { config + // Car is the client for interacting with the Car builders. + Car *CarClient // User is the client for interacting with the User builders. User *UserClient } @@ -35,6 +37,7 @@ func (tx *Tx) Client() *Client { return &Client{ config: tx.config, Schema: migrate.NewSchema(tx.driver), + Car: NewCarClient(tx.config), User: NewUserClient(tx.config), } } @@ -46,7 +49,7 @@ func (tx *Tx) Client() *Client { // of them in order to commit or rollback the transaction. // // If a closed transaction is embedded in one of the generated entities, and the entity -// applies a query, for example: User.QueryXXX(), the query will be executed +// applies a query, for example: Car.QueryXXX(), the query will be executed // through the driver which created this transaction. // // Note that txDriver is not goroutine safe. diff --git a/entc/integration/migrate/entv1/user.go b/entc/integration/migrate/entv1/user.go index b15fe3e7e..fb9676aae 100644 --- a/entc/integration/migrate/entv1/user.go +++ b/entc/integration/migrate/entv1/user.go @@ -99,6 +99,26 @@ func (u *User) assignValues(values ...interface{}) error { return nil } +// QueryParent queries the parent edge of the User. +func (u *User) QueryParent() *UserQuery { + return (&UserClient{u.config}).QueryParent(u) +} + +// QueryChildren queries the children edge of the User. +func (u *User) QueryChildren() *UserQuery { + return (&UserClient{u.config}).QueryChildren(u) +} + +// QuerySpouse queries the spouse edge of the User. +func (u *User) QuerySpouse() *UserQuery { + return (&UserClient{u.config}).QuerySpouse(u) +} + +// QueryCar queries the car edge of the User. +func (u *User) QueryCar() *CarQuery { + return (&UserClient{u.config}).QueryCar(u) +} + // Update returns a builder for updating this User. // Note that, you need to call User.Unwrap() before calling this method, if this User // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/entc/integration/migrate/entv1/user/user.go b/entc/integration/migrate/entv1/user/user.go index fc4efdb1f..0c5413d49 100644 --- a/entc/integration/migrate/entv1/user/user.go +++ b/entc/integration/migrate/entv1/user/user.go @@ -34,6 +34,25 @@ const ( // Table holds the table name of the user in the database. Table = "users" + // ParentTable is the table the holds the parent relation/edge. + ParentTable = "users" + // ParentColumn is the table column denoting the parent relation/edge. + ParentColumn = "parent_id" + // ChildrenTable is the table the holds the children relation/edge. + ChildrenTable = "users" + // ChildrenColumn is the table column denoting the children relation/edge. + ChildrenColumn = "parent_id" + // SpouseTable is the table the holds the spouse relation/edge. + SpouseTable = "users" + // SpouseColumn is the table column denoting the spouse relation/edge. + SpouseColumn = "user_spouse_id" + // CarTable is the table the holds the car relation/edge. + CarTable = "cars" + // CarInverseTable is the table name for the Car entity. + // It exists in this package in order to avoid circular dependency with the "car" package. + CarInverseTable = "cars" + // CarColumn is the table column denoting the car relation/edge. + CarColumn = "owner_id" ) // Columns holds all SQL columns are user fields. diff --git a/entc/integration/migrate/entv1/user/where.go b/entc/integration/migrate/entv1/user/where.go index b7669e540..344d8dc12 100644 --- a/entc/integration/migrate/entv1/user/where.go +++ b/entc/integration/migrate/entv1/user/where.go @@ -8,6 +8,7 @@ package user import ( "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" ) @@ -932,6 +933,126 @@ func StateNotNil() predicate.User { ) } +// HasParent applies the HasEdge predicate on the "parent" edge. +func HasParent() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ParentTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasParentWith applies the HasEdge predicate on the "parent" edge with a given conditions (other predicates). +func HasParentWith(preds ...predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + +// HasChildren applies the HasEdge predicate on the "children" edge. +func HasChildren() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ChildrenTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasChildrenWith applies the HasEdge predicate on the "children" edge with a given conditions (other predicates). +func HasChildrenWith(preds ...predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + +// HasSpouse applies the HasEdge predicate on the "spouse" edge. +func HasSpouse() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(SpouseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, SpouseTable, SpouseColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasSpouseWith applies the HasEdge predicate on the "spouse" edge with a given conditions (other predicates). +func HasSpouseWith(preds ...predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, SpouseTable, SpouseColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + +// HasCar applies the HasEdge predicate on the "car" edge. +func HasCar() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(CarTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, CarTable, CarColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasCarWith applies the HasEdge predicate on the "car" edge with a given conditions (other predicates). +func HasCarWith(preds ...predicate.Car) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(CarInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, CarTable, CarColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + // And groups list of predicates with the AND operator between them. func And(predicates ...predicate.User) predicate.User { return predicate.User( diff --git a/entc/integration/migrate/entv1/user_create.go b/entc/integration/migrate/entv1/user_create.go index 0e820163d..6e8af0f33 100644 --- a/entc/integration/migrate/entv1/user_create.go +++ b/entc/integration/migrate/entv1/user_create.go @@ -12,6 +12,7 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" "github.com/facebookincubator/ent/schema/field" ) @@ -26,6 +27,10 @@ type UserCreate struct { renamed *string blob *[]byte state *user.State + parent map[int]struct{} + children map[int]struct{} + spouse map[int]struct{} + car map[int]struct{} } // SetAge sets the age field. @@ -94,6 +99,92 @@ func (uc *UserCreate) SetNillableState(u *user.State) *UserCreate { return uc } +// SetParentID sets the parent edge to User by id. +func (uc *UserCreate) SetParentID(id int) *UserCreate { + if uc.parent == nil { + uc.parent = make(map[int]struct{}) + } + uc.parent[id] = struct{}{} + return uc +} + +// SetNillableParentID sets the parent edge to User by id if the given value is not nil. +func (uc *UserCreate) SetNillableParentID(id *int) *UserCreate { + if id != nil { + uc = uc.SetParentID(*id) + } + return uc +} + +// SetParent sets the parent edge to User. +func (uc *UserCreate) SetParent(u *User) *UserCreate { + return uc.SetParentID(u.ID) +} + +// AddChildIDs adds the children edge to User by ids. +func (uc *UserCreate) AddChildIDs(ids ...int) *UserCreate { + if uc.children == nil { + uc.children = make(map[int]struct{}) + } + for i := range ids { + uc.children[ids[i]] = struct{}{} + } + return uc +} + +// AddChildren adds the children edges to User. +func (uc *UserCreate) AddChildren(u ...*User) *UserCreate { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uc.AddChildIDs(ids...) +} + +// SetSpouseID sets the spouse edge to User by id. +func (uc *UserCreate) SetSpouseID(id int) *UserCreate { + if uc.spouse == nil { + uc.spouse = make(map[int]struct{}) + } + uc.spouse[id] = struct{}{} + return uc +} + +// SetNillableSpouseID sets the spouse edge to User by id if the given value is not nil. +func (uc *UserCreate) SetNillableSpouseID(id *int) *UserCreate { + if id != nil { + uc = uc.SetSpouseID(*id) + } + return uc +} + +// SetSpouse sets the spouse edge to User. +func (uc *UserCreate) SetSpouse(u *User) *UserCreate { + return uc.SetSpouseID(u.ID) +} + +// SetCarID sets the car edge to Car by id. +func (uc *UserCreate) SetCarID(id int) *UserCreate { + if uc.car == nil { + uc.car = make(map[int]struct{}) + } + uc.car[id] = struct{}{} + return uc +} + +// SetNillableCarID sets the car edge to Car by id if the given value is not nil. +func (uc *UserCreate) SetNillableCarID(id *int) *UserCreate { + if id != nil { + uc = uc.SetCarID(*id) + } + return uc +} + +// SetCar sets the car edge to Car. +func (uc *UserCreate) SetCar(c *Car) *UserCreate { + return uc.SetCarID(c.ID) +} + // Save creates the User in the database. func (uc *UserCreate) Save(ctx context.Context) (*User, error) { if uc.age == nil { @@ -113,6 +204,15 @@ func (uc *UserCreate) Save(ctx context.Context) (*User, error) { return nil, fmt.Errorf("entv1: validator failed for field \"state\": %v", err) } } + if len(uc.parent) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"parent\"") + } + if len(uc.spouse) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"spouse\"") + } + if len(uc.car) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"car\"") + } return uc.sqlSave(ctx) } @@ -192,6 +292,82 @@ func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) { }) u.State = *value } + if nodes := uc.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } + if nodes := uc.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } + if nodes := uc.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } + if nodes := uc.car; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } if err := sqlgraph.CreateNode(ctx, uc.driver, spec); err != nil { if cerr, ok := isSQLConstraintError(err); ok { err = cerr diff --git a/entc/integration/migrate/entv1/user_query.go b/entc/integration/migrate/entv1/user_query.go index 7ae061418..f75f278d8 100644 --- a/entc/integration/migrate/entv1/user_query.go +++ b/entc/integration/migrate/entv1/user_query.go @@ -14,6 +14,7 @@ import ( "github.com/facebookincubator/ent/dialect/sql" "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" "github.com/facebookincubator/ent/schema/field" @@ -55,6 +56,54 @@ func (uq *UserQuery) Order(o ...Order) *UserQuery { return uq } +// QueryParent chains the current query on the parent edge. +func (uq *UserQuery) QueryParent() *UserQuery { + query := &UserQuery{config: uq.config} + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, uq.sqlQuery()), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, user.ParentTable, user.ParentColumn), + ) + query.sql = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return query +} + +// QueryChildren chains the current query on the children edge. +func (uq *UserQuery) QueryChildren() *UserQuery { + query := &UserQuery{config: uq.config} + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, uq.sqlQuery()), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, user.ChildrenTable, user.ChildrenColumn), + ) + query.sql = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return query +} + +// QuerySpouse chains the current query on the spouse edge. +func (uq *UserQuery) QuerySpouse() *UserQuery { + query := &UserQuery{config: uq.config} + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, uq.sqlQuery()), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, user.SpouseTable, user.SpouseColumn), + ) + query.sql = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return query +} + +// QueryCar chains the current query on the car edge. +func (uq *UserQuery) QueryCar() *CarQuery { + query := &CarQuery{config: uq.config} + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, uq.sqlQuery()), + sqlgraph.To(car.Table, car.FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, user.CarTable, user.CarColumn), + ) + query.sql = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return query +} + // First returns the first User entity in the query. Returns *ErrNotFound when no user was found. func (uq *UserQuery) First(ctx context.Context) (*User, error) { us, err := uq.Limit(1).All(ctx) diff --git a/entc/integration/migrate/entv1/user_update.go b/entc/integration/migrate/entv1/user_update.go index 4e2e5551f..7bf3c51de 100644 --- a/entc/integration/migrate/entv1/user_update.go +++ b/entc/integration/migrate/entv1/user_update.go @@ -8,10 +8,12 @@ package entv1 import ( "context" + "errors" "fmt" "github.com/facebookincubator/ent/dialect/sql" "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv1/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/predicate" "github.com/facebookincubator/ent/entc/integration/migrate/entv1/user" "github.com/facebookincubator/ent/schema/field" @@ -20,19 +22,27 @@ import ( // UserUpdate is the builder for updating User entities. type UserUpdate struct { config - age *int32 - addage *int32 - name *string - nickname *string - address *string - clearaddress bool - renamed *string - clearrenamed bool - blob *[]byte - clearblob bool - state *user.State - clearstate bool - predicates []predicate.User + age *int32 + addage *int32 + name *string + nickname *string + address *string + clearaddress bool + renamed *string + clearrenamed bool + blob *[]byte + clearblob bool + state *user.State + clearstate bool + parent map[int]struct{} + children map[int]struct{} + spouse map[int]struct{} + car map[int]struct{} + clearedParent bool + removedChildren map[int]struct{} + clearedSpouse bool + clearedCar bool + predicates []predicate.User } // Where adds a new predicate for the builder. @@ -146,6 +156,130 @@ func (uu *UserUpdate) ClearState() *UserUpdate { return uu } +// SetParentID sets the parent edge to User by id. +func (uu *UserUpdate) SetParentID(id int) *UserUpdate { + if uu.parent == nil { + uu.parent = make(map[int]struct{}) + } + uu.parent[id] = struct{}{} + return uu +} + +// SetNillableParentID sets the parent edge to User by id if the given value is not nil. +func (uu *UserUpdate) SetNillableParentID(id *int) *UserUpdate { + if id != nil { + uu = uu.SetParentID(*id) + } + return uu +} + +// SetParent sets the parent edge to User. +func (uu *UserUpdate) SetParent(u *User) *UserUpdate { + return uu.SetParentID(u.ID) +} + +// AddChildIDs adds the children edge to User by ids. +func (uu *UserUpdate) AddChildIDs(ids ...int) *UserUpdate { + if uu.children == nil { + uu.children = make(map[int]struct{}) + } + for i := range ids { + uu.children[ids[i]] = struct{}{} + } + return uu +} + +// AddChildren adds the children edges to User. +func (uu *UserUpdate) AddChildren(u ...*User) *UserUpdate { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uu.AddChildIDs(ids...) +} + +// SetSpouseID sets the spouse edge to User by id. +func (uu *UserUpdate) SetSpouseID(id int) *UserUpdate { + if uu.spouse == nil { + uu.spouse = make(map[int]struct{}) + } + uu.spouse[id] = struct{}{} + return uu +} + +// SetNillableSpouseID sets the spouse edge to User by id if the given value is not nil. +func (uu *UserUpdate) SetNillableSpouseID(id *int) *UserUpdate { + if id != nil { + uu = uu.SetSpouseID(*id) + } + return uu +} + +// SetSpouse sets the spouse edge to User. +func (uu *UserUpdate) SetSpouse(u *User) *UserUpdate { + return uu.SetSpouseID(u.ID) +} + +// SetCarID sets the car edge to Car by id. +func (uu *UserUpdate) SetCarID(id int) *UserUpdate { + if uu.car == nil { + uu.car = make(map[int]struct{}) + } + uu.car[id] = struct{}{} + return uu +} + +// SetNillableCarID sets the car edge to Car by id if the given value is not nil. +func (uu *UserUpdate) SetNillableCarID(id *int) *UserUpdate { + if id != nil { + uu = uu.SetCarID(*id) + } + return uu +} + +// SetCar sets the car edge to Car. +func (uu *UserUpdate) SetCar(c *Car) *UserUpdate { + return uu.SetCarID(c.ID) +} + +// ClearParent clears the parent edge to User. +func (uu *UserUpdate) ClearParent() *UserUpdate { + uu.clearedParent = true + return uu +} + +// RemoveChildIDs removes the children edge to User by ids. +func (uu *UserUpdate) RemoveChildIDs(ids ...int) *UserUpdate { + if uu.removedChildren == nil { + uu.removedChildren = make(map[int]struct{}) + } + for i := range ids { + uu.removedChildren[ids[i]] = struct{}{} + } + return uu +} + +// RemoveChildren removes children edges to User. +func (uu *UserUpdate) RemoveChildren(u ...*User) *UserUpdate { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uu.RemoveChildIDs(ids...) +} + +// ClearSpouse clears the spouse edge to User. +func (uu *UserUpdate) ClearSpouse() *UserUpdate { + uu.clearedSpouse = true + return uu +} + +// ClearCar clears the car edge to Car. +func (uu *UserUpdate) ClearCar() *UserUpdate { + uu.clearedCar = true + return uu +} + // Save executes the query and returns the number of rows/vertices matched by this operation. func (uu *UserUpdate) Save(ctx context.Context) (int, error) { if uu.name != nil { @@ -158,6 +292,15 @@ func (uu *UserUpdate) Save(ctx context.Context) (int, error) { return 0, fmt.Errorf("entv1: validator failed for field \"state\": %v", err) } } + if len(uu.parent) > 1 { + return 0, errors.New("entv1: multiple assignments on a unique edge \"parent\"") + } + if len(uu.spouse) > 1 { + return 0, errors.New("entv1: multiple assignments on a unique edge \"spouse\"") + } + if len(uu.car) > 1 { + return 0, errors.New("entv1: multiple assignments on a unique edge \"car\"") + } return uu.sqlSave(ctx) } @@ -281,6 +424,149 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: user.FieldState, }) } + if uu.clearedParent { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if nodes := uu.removedChildren; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if uu.clearedSpouse { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if uu.clearedCar { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.car; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + 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, uu.driver, spec); err != nil { if cerr, ok := isSQLConstraintError(err); ok { err = cerr @@ -293,19 +579,27 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { // UserUpdateOne is the builder for updating a single User entity. type UserUpdateOne struct { config - id int - age *int32 - addage *int32 - name *string - nickname *string - address *string - clearaddress bool - renamed *string - clearrenamed bool - blob *[]byte - clearblob bool - state *user.State - clearstate bool + id int + age *int32 + addage *int32 + name *string + nickname *string + address *string + clearaddress bool + renamed *string + clearrenamed bool + blob *[]byte + clearblob bool + state *user.State + clearstate bool + parent map[int]struct{} + children map[int]struct{} + spouse map[int]struct{} + car map[int]struct{} + clearedParent bool + removedChildren map[int]struct{} + clearedSpouse bool + clearedCar bool } // SetAge sets the age field. @@ -413,6 +707,130 @@ func (uuo *UserUpdateOne) ClearState() *UserUpdateOne { return uuo } +// SetParentID sets the parent edge to User by id. +func (uuo *UserUpdateOne) SetParentID(id int) *UserUpdateOne { + if uuo.parent == nil { + uuo.parent = make(map[int]struct{}) + } + uuo.parent[id] = struct{}{} + return uuo +} + +// SetNillableParentID sets the parent edge to User by id if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableParentID(id *int) *UserUpdateOne { + if id != nil { + uuo = uuo.SetParentID(*id) + } + return uuo +} + +// SetParent sets the parent edge to User. +func (uuo *UserUpdateOne) SetParent(u *User) *UserUpdateOne { + return uuo.SetParentID(u.ID) +} + +// AddChildIDs adds the children edge to User by ids. +func (uuo *UserUpdateOne) AddChildIDs(ids ...int) *UserUpdateOne { + if uuo.children == nil { + uuo.children = make(map[int]struct{}) + } + for i := range ids { + uuo.children[ids[i]] = struct{}{} + } + return uuo +} + +// AddChildren adds the children edges to User. +func (uuo *UserUpdateOne) AddChildren(u ...*User) *UserUpdateOne { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uuo.AddChildIDs(ids...) +} + +// SetSpouseID sets the spouse edge to User by id. +func (uuo *UserUpdateOne) SetSpouseID(id int) *UserUpdateOne { + if uuo.spouse == nil { + uuo.spouse = make(map[int]struct{}) + } + uuo.spouse[id] = struct{}{} + return uuo +} + +// SetNillableSpouseID sets the spouse edge to User by id if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableSpouseID(id *int) *UserUpdateOne { + if id != nil { + uuo = uuo.SetSpouseID(*id) + } + return uuo +} + +// SetSpouse sets the spouse edge to User. +func (uuo *UserUpdateOne) SetSpouse(u *User) *UserUpdateOne { + return uuo.SetSpouseID(u.ID) +} + +// SetCarID sets the car edge to Car by id. +func (uuo *UserUpdateOne) SetCarID(id int) *UserUpdateOne { + if uuo.car == nil { + uuo.car = make(map[int]struct{}) + } + uuo.car[id] = struct{}{} + return uuo +} + +// SetNillableCarID sets the car edge to Car by id if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableCarID(id *int) *UserUpdateOne { + if id != nil { + uuo = uuo.SetCarID(*id) + } + return uuo +} + +// SetCar sets the car edge to Car. +func (uuo *UserUpdateOne) SetCar(c *Car) *UserUpdateOne { + return uuo.SetCarID(c.ID) +} + +// ClearParent clears the parent edge to User. +func (uuo *UserUpdateOne) ClearParent() *UserUpdateOne { + uuo.clearedParent = true + return uuo +} + +// RemoveChildIDs removes the children edge to User by ids. +func (uuo *UserUpdateOne) RemoveChildIDs(ids ...int) *UserUpdateOne { + if uuo.removedChildren == nil { + uuo.removedChildren = make(map[int]struct{}) + } + for i := range ids { + uuo.removedChildren[ids[i]] = struct{}{} + } + return uuo +} + +// RemoveChildren removes children edges to User. +func (uuo *UserUpdateOne) RemoveChildren(u ...*User) *UserUpdateOne { + ids := make([]int, len(u)) + for i := range u { + ids[i] = u[i].ID + } + return uuo.RemoveChildIDs(ids...) +} + +// ClearSpouse clears the spouse edge to User. +func (uuo *UserUpdateOne) ClearSpouse() *UserUpdateOne { + uuo.clearedSpouse = true + return uuo +} + +// ClearCar clears the car edge to Car. +func (uuo *UserUpdateOne) ClearCar() *UserUpdateOne { + uuo.clearedCar = true + return uuo +} + // Save executes the query and returns the updated entity. func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { if uuo.name != nil { @@ -425,6 +843,15 @@ func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { return nil, fmt.Errorf("entv1: validator failed for field \"state\": %v", err) } } + if len(uuo.parent) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"parent\"") + } + if len(uuo.spouse) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"spouse\"") + } + if len(uuo.car) > 1 { + return nil, errors.New("entv1: multiple assignments on a unique edge \"car\"") + } return uuo.sqlSave(ctx) } @@ -542,6 +969,149 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { Column: user.FieldState, }) } + if uuo.clearedParent { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.parent; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: user.ParentTable, + Columns: []string{user.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if nodes := uuo.removedChildren; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.children; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.ChildrenTable, + Columns: []string{user.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if uuo.clearedSpouse { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.spouse; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.SpouseTable, + Columns: []string{user.SpouseColumn}, + Bidi: true, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + if uuo.clearedCar { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.car; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } u = &User{config: uuo.config} spec.Assign = u.assignValues spec.ScanValues = u.scanValues() diff --git a/entc/integration/migrate/entv2/car.go b/entc/integration/migrate/entv2/car.go new file mode 100644 index 000000000..68036d840 --- /dev/null +++ b/entc/integration/migrate/entv2/car.go @@ -0,0 +1,85 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv2 + +import ( + "fmt" + "strings" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" +) + +// Car is the model entity for the Car schema. +type Car struct { + config + // ID of the ent. + ID int `json:"id,omitempty"` +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Car) scanValues() []interface{} { + return []interface{}{ + &sql.NullInt64{}, + } +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Car fields. +func (c *Car) assignValues(values ...interface{}) error { + if m, n := len(values), len(car.Columns); m != n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + value, ok := values[0].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = int(value.Int64) + values = values[1:] + return nil +} + +// QueryOwner queries the owner edge of the Car. +func (c *Car) QueryOwner() *UserQuery { + return (&CarClient{c.config}).QueryOwner(c) +} + +// Update returns a builder for updating this Car. +// Note that, you need to call Car.Unwrap() before calling this method, if this Car +// was returned from a transaction, and the transaction was committed or rolled back. +func (c *Car) Update() *CarUpdateOne { + return (&CarClient{c.config}).UpdateOne(c) +} + +// Unwrap unwraps the entity that was returned from a transaction after it was closed, +// so that all next queries will be executed through the driver which created the transaction. +func (c *Car) Unwrap() *Car { + tx, ok := c.config.driver.(*txDriver) + if !ok { + panic("entv2: Car is not a transactional entity") + } + c.config.driver = tx.drv + return c +} + +// String implements the fmt.Stringer. +func (c *Car) String() string { + var builder strings.Builder + builder.WriteString("Car(") + builder.WriteString(fmt.Sprintf("id=%v", c.ID)) + builder.WriteByte(')') + return builder.String() +} + +// Cars is a parsable slice of Car. +type Cars []*Car + +func (c Cars) config(cfg config) { + for _i := range c { + c[_i].config = cfg + } +} diff --git a/entc/integration/migrate/entv2/car/car.go b/entc/integration/migrate/entv2/car/car.go new file mode 100644 index 000000000..9738845d9 --- /dev/null +++ b/entc/integration/migrate/entv2/car/car.go @@ -0,0 +1,29 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package car + +const ( + // Label holds the string label denoting the car type in the database. + Label = "car" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + + // Table holds the table name of the car in the database. + Table = "cars" + // OwnerTable is the table the holds the owner relation/edge. + OwnerTable = "cars" + // OwnerInverseTable is the table name for the User entity. + // It exists in this package in order to avoid circular dependency with the "user" package. + OwnerInverseTable = "users" + // OwnerColumn is the table column denoting the owner relation/edge. + OwnerColumn = "owner_id" +) + +// Columns holds all SQL columns are car fields. +var Columns = []string{ + FieldID, +} diff --git a/entc/integration/migrate/entv2/car/where.go b/entc/integration/migrate/entv2/car/where.go new file mode 100644 index 000000000..06149006a --- /dev/null +++ b/entc/integration/migrate/entv2/car/where.go @@ -0,0 +1,174 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package car + +import ( + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" +) + +// ID filters vertices based on their identifier. +func ID(id int) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }, + ) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }, + ) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }, + ) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Car { + 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(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }, + ) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Car { + 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(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }, + ) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }, + ) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }, + ) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }, + ) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }, + ) +} + +// HasOwner applies the HasEdge predicate on the "owner" edge. +func HasOwner() predicate.Car { + return predicate.Car(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(OwnerTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, OwnerTable, OwnerColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasOwnerWith applies the HasEdge predicate on the "owner" edge with a given conditions (other predicates). +func HasOwnerWith(preds ...predicate.User) predicate.Car { + return predicate.Car(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(OwnerInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, OwnerTable, OwnerColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + +// And groups list of predicates with the AND operator between them. +func And(predicates ...predicate.Car) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }, + ) +} + +// Or groups list of predicates with the OR operator between them. +func Or(predicates ...predicate.Car) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }, + ) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Car) predicate.Car { + return predicate.Car( + func(s *sql.Selector) { + p(s.Not()) + }, + ) +} diff --git a/entc/integration/migrate/entv2/car_create.go b/entc/integration/migrate/entv2/car_create.go new file mode 100644 index 000000000..f5ad3b706 --- /dev/null +++ b/entc/integration/migrate/entv2/car_create.go @@ -0,0 +1,103 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv2 + +import ( + "context" + "errors" + + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" + "github.com/facebookincubator/ent/schema/field" +) + +// CarCreate is the builder for creating a Car entity. +type CarCreate struct { + config + owner map[int]struct{} +} + +// SetOwnerID sets the owner edge to User by id. +func (cc *CarCreate) SetOwnerID(id int) *CarCreate { + if cc.owner == nil { + cc.owner = make(map[int]struct{}) + } + cc.owner[id] = struct{}{} + return cc +} + +// SetNillableOwnerID sets the owner edge to User by id if the given value is not nil. +func (cc *CarCreate) SetNillableOwnerID(id *int) *CarCreate { + if id != nil { + cc = cc.SetOwnerID(*id) + } + return cc +} + +// SetOwner sets the owner edge to User. +func (cc *CarCreate) SetOwner(u *User) *CarCreate { + return cc.SetOwnerID(u.ID) +} + +// Save creates the Car in the database. +func (cc *CarCreate) Save(ctx context.Context) (*Car, error) { + if len(cc.owner) > 1 { + return nil, errors.New("entv2: multiple assignments on a unique edge \"owner\"") + } + return cc.sqlSave(ctx) +} + +// SaveX calls Save and panics if Save returns an error. +func (cc *CarCreate) SaveX(ctx context.Context) *Car { + v, err := cc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cc *CarCreate) sqlSave(ctx context.Context) (*Car, error) { + var ( + c = &Car{config: cc.config} + spec = &sqlgraph.CreateSpec{ + Table: car.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + } + ) + if nodes := cc.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } + if err := sqlgraph.CreateNode(ctx, cc.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } + return nil, err + } + id := spec.ID.Value.(int64) + c.ID = int(id) + return c, nil +} diff --git a/entc/integration/migrate/entv2/car_delete.go b/entc/integration/migrate/entv2/car_delete.go new file mode 100644 index 000000000..d31a8cf94 --- /dev/null +++ b/entc/integration/migrate/entv2/car_delete.go @@ -0,0 +1,86 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv2 + +import ( + "context" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" + "github.com/facebookincubator/ent/schema/field" +) + +// CarDelete is the builder for deleting a Car entity. +type CarDelete struct { + config + predicates []predicate.Car +} + +// Where adds a new predicate to the delete builder. +func (cd *CarDelete) Where(ps ...predicate.Car) *CarDelete { + cd.predicates = append(cd.predicates, ps...) + return cd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (cd *CarDelete) Exec(ctx context.Context) (int, error) { + return cd.sqlExec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (cd *CarDelete) ExecX(ctx context.Context) int { + n, err := cd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (cd *CarDelete) sqlExec(ctx context.Context) (int, error) { + spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + if ps := cd.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, cd.driver, spec) +} + +// CarDeleteOne is the builder for deleting a single Car entity. +type CarDeleteOne struct { + cd *CarDelete +} + +// Exec executes the deletion query. +func (cdo *CarDeleteOne) Exec(ctx context.Context) error { + n, err := cdo.cd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &ErrNotFound{car.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (cdo *CarDeleteOne) ExecX(ctx context.Context) { + cdo.cd.ExecX(ctx) +} diff --git a/entc/integration/migrate/entv2/car_query.go b/entc/integration/migrate/entv2/car_query.go new file mode 100644 index 000000000..6f291b16d --- /dev/null +++ b/entc/integration/migrate/entv2/car_query.go @@ -0,0 +1,603 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv2 + +import ( + "context" + "errors" + "fmt" + "math" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" + "github.com/facebookincubator/ent/schema/field" +) + +// CarQuery is the builder for querying Car entities. +type CarQuery struct { + config + limit *int + offset *int + order []Order + unique []string + predicates []predicate.Car + // intermediate query. + sql *sql.Selector +} + +// Where adds a new predicate for the builder. +func (cq *CarQuery) Where(ps ...predicate.Car) *CarQuery { + cq.predicates = append(cq.predicates, ps...) + return cq +} + +// Limit adds a limit step to the query. +func (cq *CarQuery) Limit(limit int) *CarQuery { + cq.limit = &limit + return cq +} + +// Offset adds an offset step to the query. +func (cq *CarQuery) Offset(offset int) *CarQuery { + cq.offset = &offset + return cq +} + +// Order adds an order step to the query. +func (cq *CarQuery) Order(o ...Order) *CarQuery { + cq.order = append(cq.order, o...) + return cq +} + +// QueryOwner chains the current query on the owner edge. +func (cq *CarQuery) QueryOwner() *UserQuery { + query := &UserQuery{config: cq.config} + step := sqlgraph.NewStep( + sqlgraph.From(car.Table, car.FieldID, cq.sqlQuery()), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, car.OwnerTable, car.OwnerColumn), + ) + query.sql = sqlgraph.SetNeighbors(cq.driver.Dialect(), step) + return query +} + +// First returns the first Car entity in the query. Returns *ErrNotFound when no car was found. +func (cq *CarQuery) First(ctx context.Context) (*Car, error) { + cs, err := cq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(cs) == 0 { + return nil, &ErrNotFound{car.Label} + } + return cs[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (cq *CarQuery) FirstX(ctx context.Context) *Car { + c, err := cq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return c +} + +// FirstID returns the first Car id in the query. Returns *ErrNotFound when no id was found. +func (cq *CarQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = cq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &ErrNotFound{car.Label} + return + } + return ids[0], nil +} + +// FirstXID is like FirstID, but panics if an error occurs. +func (cq *CarQuery) FirstXID(ctx context.Context) int { + id, err := cq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns the only Car entity in the query, returns an error if not exactly one entity was returned. +func (cq *CarQuery) Only(ctx context.Context) (*Car, error) { + cs, err := cq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(cs) { + case 1: + return cs[0], nil + case 0: + return nil, &ErrNotFound{car.Label} + default: + return nil, &ErrNotSingular{car.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (cq *CarQuery) OnlyX(ctx context.Context) *Car { + c, err := cq.Only(ctx) + if err != nil { + panic(err) + } + return c +} + +// OnlyID returns the only Car id in the query, returns an error if not exactly one id was returned. +func (cq *CarQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = cq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &ErrNotFound{car.Label} + default: + err = &ErrNotSingular{car.Label} + } + return +} + +// OnlyXID is like OnlyID, but panics if an error occurs. +func (cq *CarQuery) OnlyXID(ctx context.Context) int { + id, err := cq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Cars. +func (cq *CarQuery) All(ctx context.Context) ([]*Car, error) { + return cq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (cq *CarQuery) AllX(ctx context.Context) []*Car { + cs, err := cq.All(ctx) + if err != nil { + panic(err) + } + return cs +} + +// IDs executes the query and returns a list of Car ids. +func (cq *CarQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := cq.Select(car.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (cq *CarQuery) IDsX(ctx context.Context) []int { + ids, err := cq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (cq *CarQuery) Count(ctx context.Context) (int, error) { + return cq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (cq *CarQuery) CountX(ctx context.Context) int { + count, err := cq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (cq *CarQuery) Exist(ctx context.Context) (bool, error) { + return cq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (cq *CarQuery) ExistX(ctx context.Context) bool { + exist, err := cq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the query builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (cq *CarQuery) Clone() *CarQuery { + return &CarQuery{ + config: cq.config, + limit: cq.limit, + offset: cq.offset, + order: append([]Order{}, cq.order...), + unique: append([]string{}, cq.unique...), + predicates: append([]predicate.Car{}, cq.predicates...), + // clone intermediate query. + sql: cq.sql.Clone(), + } +} + +// GroupBy used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +func (cq *CarQuery) GroupBy(field string, fields ...string) *CarGroupBy { + group := &CarGroupBy{config: cq.config} + group.fields = append([]string{field}, fields...) + group.sql = cq.sqlQuery() + return group +} + +// Select one or more fields from the given query. +func (cq *CarQuery) Select(field string, fields ...string) *CarSelect { + selector := &CarSelect{config: cq.config} + selector.fields = append([]string{field}, fields...) + selector.sql = cq.sqlQuery() + return selector +} + +func (cq *CarQuery) sqlAll(ctx context.Context) ([]*Car, error) { + var ( + nodes []*Car + spec = cq.querySpec() + ) + spec.ScanValues = func() []interface{} { + node := &Car{config: cq.config} + nodes = append(nodes, node) + return node.scanValues() + } + spec.Assign = func(values ...interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("entv2: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + return node.assignValues(values...) + } + if err := sqlgraph.QueryNodes(ctx, cq.driver, spec); err != nil { + return nil, err + } + return nodes, nil +} + +func (cq *CarQuery) sqlCount(ctx context.Context) (int, error) { + spec := cq.querySpec() + return sqlgraph.CountNodes(ctx, cq.driver, spec) +} + +func (cq *CarQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := cq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("entv2: check existence: %v", err) + } + return n > 0, nil +} + +func (cq *CarQuery) querySpec() *sqlgraph.QuerySpec { + spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + From: cq.sql, + Unique: true, + } + if ps := cq.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := cq.limit; limit != nil { + spec.Limit = *limit + } + if offset := cq.offset; offset != nil { + spec.Offset = *offset + } + if ps := cq.order; len(ps) > 0 { + spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return spec +} + +func (cq *CarQuery) sqlQuery() *sql.Selector { + builder := sql.Dialect(cq.driver.Dialect()) + t1 := builder.Table(car.Table) + selector := builder.Select(t1.Columns(car.Columns...)...).From(t1) + if cq.sql != nil { + selector = cq.sql + selector.Select(selector.Columns(car.Columns...)...) + } + for _, p := range cq.predicates { + p(selector) + } + for _, p := range cq.order { + p(selector) + } + if offset := cq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := cq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// CarGroupBy is the builder for group-by Car entities. +type CarGroupBy struct { + config + fields []string + fns []Aggregate + // intermediate query. + sql *sql.Selector +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (cgb *CarGroupBy) Aggregate(fns ...Aggregate) *CarGroupBy { + cgb.fns = append(cgb.fns, fns...) + return cgb +} + +// Scan applies the group-by query and scan the result into the given value. +func (cgb *CarGroupBy) Scan(ctx context.Context, v interface{}) error { + return cgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (cgb *CarGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := cgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv2: CarGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (cgb *CarGroupBy) StringsX(ctx context.Context) []string { + v, err := cgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv2: CarGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (cgb *CarGroupBy) IntsX(ctx context.Context) []int { + v, err := cgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv2: CarGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (cgb *CarGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := cgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. It is only allowed when querying group-by with one field. +func (cgb *CarGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("entv2: CarGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (cgb *CarGroupBy) BoolsX(ctx context.Context) []bool { + v, err := cgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cgb *CarGroupBy) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := cgb.sqlQuery().Query() + if err := cgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (cgb *CarGroupBy) sqlQuery() *sql.Selector { + selector := cgb.sql + columns := make([]string, 0, len(cgb.fields)+len(cgb.fns)) + columns = append(columns, cgb.fields...) + for _, fn := range cgb.fns { + columns = append(columns, fn(selector)) + } + return selector.Select(columns...).GroupBy(cgb.fields...) +} + +// CarSelect is the builder for select fields of Car entities. +type CarSelect struct { + config + fields []string + // intermediate queries. + sql *sql.Selector +} + +// Scan applies the selector query and scan the result into the given value. +func (cs *CarSelect) Scan(ctx context.Context, v interface{}) error { + return cs.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (cs *CarSelect) ScanX(ctx context.Context, v interface{}) { + if err := cs.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Strings(ctx context.Context) ([]string, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv2: CarSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (cs *CarSelect) StringsX(ctx context.Context) []string { + v, err := cs.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Ints(ctx context.Context) ([]int, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv2: CarSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (cs *CarSelect) IntsX(ctx context.Context) []int { + v, err := cs.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv2: CarSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (cs *CarSelect) Float64sX(ctx context.Context) []float64 { + v, err := cs.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from selector. It is only allowed when selecting one field. +func (cs *CarSelect) Bools(ctx context.Context) ([]bool, error) { + if len(cs.fields) > 1 { + return nil, errors.New("entv2: CarSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (cs *CarSelect) BoolsX(ctx context.Context) []bool { + v, err := cs.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cs *CarSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := cs.sqlQuery().Query() + if err := cs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (cs *CarSelect) sqlQuery() sql.Querier { + selector := cs.sql + selector.Select(selector.Columns(cs.fields...)...) + return selector +} diff --git a/entc/integration/migrate/entv2/car_update.go b/entc/integration/migrate/entv2/car_update.go new file mode 100644 index 000000000..e55c05b33 --- /dev/null +++ b/entc/integration/migrate/entv2/car_update.go @@ -0,0 +1,278 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +// Code generated by entc, DO NOT EDIT. + +package entv2 + +import ( + "context" + "errors" + + "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" + "github.com/facebookincubator/ent/schema/field" +) + +// CarUpdate is the builder for updating Car entities. +type CarUpdate struct { + config + owner map[int]struct{} + clearedOwner bool + predicates []predicate.Car +} + +// Where adds a new predicate for the builder. +func (cu *CarUpdate) Where(ps ...predicate.Car) *CarUpdate { + cu.predicates = append(cu.predicates, ps...) + return cu +} + +// SetOwnerID sets the owner edge to User by id. +func (cu *CarUpdate) SetOwnerID(id int) *CarUpdate { + if cu.owner == nil { + cu.owner = make(map[int]struct{}) + } + cu.owner[id] = struct{}{} + return cu +} + +// SetNillableOwnerID sets the owner edge to User by id if the given value is not nil. +func (cu *CarUpdate) SetNillableOwnerID(id *int) *CarUpdate { + if id != nil { + cu = cu.SetOwnerID(*id) + } + return cu +} + +// SetOwner sets the owner edge to User. +func (cu *CarUpdate) SetOwner(u *User) *CarUpdate { + return cu.SetOwnerID(u.ID) +} + +// ClearOwner clears the owner edge to User. +func (cu *CarUpdate) ClearOwner() *CarUpdate { + cu.clearedOwner = true + return cu +} + +// Save executes the query and returns the number of rows/vertices matched by this operation. +func (cu *CarUpdate) Save(ctx context.Context) (int, error) { + if len(cu.owner) > 1 { + return 0, errors.New("entv2: multiple assignments on a unique edge \"owner\"") + } + return cu.sqlSave(ctx) +} + +// SaveX is like Save, but panics if an error occurs. +func (cu *CarUpdate) SaveX(ctx context.Context) int { + affected, err := cu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (cu *CarUpdate) Exec(ctx context.Context) error { + _, err := cu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cu *CarUpdate) ExecX(ctx context.Context) { + if err := cu.Exec(ctx); err != nil { + panic(err) + } +} + +func (cu *CarUpdate) sqlSave(ctx context.Context) (n int, err error) { + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + if ps := cu.predicates; len(ps) > 0 { + spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if cu.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := cu.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.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, cu.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } + return 0, err + } + return n, nil +} + +// CarUpdateOne is the builder for updating a single Car entity. +type CarUpdateOne struct { + config + id int + owner map[int]struct{} + clearedOwner bool +} + +// SetOwnerID sets the owner edge to User by id. +func (cuo *CarUpdateOne) SetOwnerID(id int) *CarUpdateOne { + if cuo.owner == nil { + cuo.owner = make(map[int]struct{}) + } + cuo.owner[id] = struct{}{} + return cuo +} + +// SetNillableOwnerID sets the owner edge to User by id if the given value is not nil. +func (cuo *CarUpdateOne) SetNillableOwnerID(id *int) *CarUpdateOne { + if id != nil { + cuo = cuo.SetOwnerID(*id) + } + return cuo +} + +// SetOwner sets the owner edge to User. +func (cuo *CarUpdateOne) SetOwner(u *User) *CarUpdateOne { + return cuo.SetOwnerID(u.ID) +} + +// ClearOwner clears the owner edge to User. +func (cuo *CarUpdateOne) ClearOwner() *CarUpdateOne { + cuo.clearedOwner = true + return cuo +} + +// Save executes the query and returns the updated entity. +func (cuo *CarUpdateOne) Save(ctx context.Context) (*Car, error) { + if len(cuo.owner) > 1 { + return nil, errors.New("entv2: multiple assignments on a unique edge \"owner\"") + } + return cuo.sqlSave(ctx) +} + +// SaveX is like Save, but panics if an error occurs. +func (cuo *CarUpdateOne) SaveX(ctx context.Context) *Car { + c, err := cuo.Save(ctx) + if err != nil { + panic(err) + } + return c +} + +// Exec executes the query on the entity. +func (cuo *CarUpdateOne) Exec(ctx context.Context) error { + _, err := cuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cuo *CarUpdateOne) ExecX(ctx context.Context) { + if err := cuo.Exec(ctx); err != nil { + panic(err) + } +} + +func (cuo *CarUpdateOne) sqlSave(ctx context.Context) (c *Car, err error) { + spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: car.Table, + Columns: car.Columns, + ID: &sqlgraph.FieldSpec{ + Value: cuo.id, + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + if cuo.clearedOwner { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := cuo.owner; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: car.OwnerTable, + Columns: []string{car.OwnerColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } + c = &Car{config: cuo.config} + spec.Assign = c.assignValues + spec.ScanValues = c.scanValues() + if err = sqlgraph.UpdateNode(ctx, cuo.driver, spec); err != nil { + if cerr, ok := isSQLConstraintError(err); ok { + err = cerr + } + return nil, err + } + return c, nil +} diff --git a/entc/integration/migrate/entv2/client.go b/entc/integration/migrate/entv2/client.go index 4995ff891..829f54d63 100644 --- a/entc/integration/migrate/entv2/client.go +++ b/entc/integration/migrate/entv2/client.go @@ -13,12 +13,14 @@ import ( "github.com/facebookincubator/ent/entc/integration/migrate/entv2/migrate" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/group" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/pet" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" "github.com/facebookincubator/ent/dialect" "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" ) // Client is the client that holds all ent builders. @@ -26,6 +28,8 @@ type Client struct { config // Schema is the client for creating, migrating and dropping schema. Schema *migrate.Schema + // Car is the client for interacting with the Car builders. + Car *CarClient // Group is the client for interacting with the Group builders. Group *GroupClient // Pet is the client for interacting with the Pet builders. @@ -41,6 +45,7 @@ func NewClient(opts ...Option) *Client { return &Client{ config: c, Schema: migrate.NewSchema(c.driver), + Car: NewCarClient(c), Group: NewGroupClient(c), Pet: NewPetClient(c), User: NewUserClient(c), @@ -75,6 +80,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := config{driver: tx, log: c.log, debug: c.debug} return &Tx{ config: cfg, + Car: NewCarClient(cfg), Group: NewGroupClient(cfg), Pet: NewPetClient(cfg), User: NewUserClient(cfg), @@ -84,7 +90,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { // Debug returns a new debug-client. It's used to get verbose logging on specific operations. // // client.Debug(). -// Group. +// Car. // Query(). // Count(ctx) // @@ -96,6 +102,7 @@ func (c *Client) Debug() *Client { return &Client{ config: cfg, Schema: migrate.NewSchema(cfg.driver), + Car: NewCarClient(cfg), Group: NewGroupClient(cfg), Pet: NewPetClient(cfg), User: NewUserClient(cfg), @@ -107,6 +114,84 @@ func (c *Client) Close() error { return c.driver.Close() } +// CarClient is a client for the Car schema. +type CarClient struct { + config +} + +// NewCarClient returns a client for the Car from the given config. +func NewCarClient(c config) *CarClient { + return &CarClient{config: c} +} + +// Create returns a create builder for Car. +func (c *CarClient) Create() *CarCreate { + return &CarCreate{config: c.config} +} + +// Update returns an update builder for Car. +func (c *CarClient) Update() *CarUpdate { + return &CarUpdate{config: c.config} +} + +// UpdateOne returns an update builder for the given entity. +func (c *CarClient) UpdateOne(ca *Car) *CarUpdateOne { + return c.UpdateOneID(ca.ID) +} + +// UpdateOneID returns an update builder for the given id. +func (c *CarClient) UpdateOneID(id int) *CarUpdateOne { + return &CarUpdateOne{config: c.config, id: id} +} + +// Delete returns a delete builder for Car. +func (c *CarClient) Delete() *CarDelete { + return &CarDelete{config: c.config} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *CarClient) DeleteOne(ca *Car) *CarDeleteOne { + return c.DeleteOneID(ca.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *CarClient) DeleteOneID(id int) *CarDeleteOne { + return &CarDeleteOne{c.Delete().Where(car.ID(id))} +} + +// Create returns a query builder for Car. +func (c *CarClient) Query() *CarQuery { + return &CarQuery{config: c.config} +} + +// Get returns a Car entity by its id. +func (c *CarClient) Get(ctx context.Context, id int) (*Car, error) { + return c.Query().Where(car.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *CarClient) GetX(ctx context.Context, id int) *Car { + ca, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return ca +} + +// QueryOwner queries the owner edge of a Car. +func (c *CarClient) QueryOwner(ca *Car) *UserQuery { + query := &UserQuery{config: c.config} + id := ca.ID + step := sqlgraph.NewStep( + sqlgraph.From(car.Table, car.FieldID, id), + sqlgraph.To(user.Table, user.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, car.OwnerTable, car.OwnerColumn), + ) + query.sql = sqlgraph.Neighbors(ca.driver.Dialect(), step) + + return query +} + // GroupClient is a client for the Group schema. type GroupClient struct { config @@ -298,3 +383,17 @@ func (c *UserClient) GetX(ctx context.Context, id int) *User { } return u } + +// QueryCar queries the car edge of a User. +func (c *UserClient) QueryCar(u *User) *CarQuery { + query := &CarQuery{config: c.config} + id := u.ID + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, id), + sqlgraph.To(car.Table, car.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, user.CarTable, user.CarColumn), + ) + query.sql = sqlgraph.Neighbors(u.driver.Dialect(), step) + + return query +} diff --git a/entc/integration/migrate/entv2/example_test.go b/entc/integration/migrate/entv2/example_test.go index 4501fdbde..ba7f23d49 100644 --- a/entc/integration/migrate/entv2/example_test.go +++ b/entc/integration/migrate/entv2/example_test.go @@ -21,6 +21,29 @@ import ( // var dsn string +func ExampleCar() { + if dsn == "" { + return + } + ctx := context.Background() + drv, err := sql.Open("mysql", dsn) + if err != nil { + log.Fatalf("failed creating database client: %v", err) + } + defer drv.Close() + client := NewClient(Driver(drv)) + // creating vertices for the car's edges. + + // create car vertex with its edges. + c := client.Car. + Create(). + SaveX(ctx) + log.Println("car created:", c) + + // query edges. + + // Output: +} func ExampleGroup() { if dsn == "" { return @@ -79,6 +102,10 @@ func ExampleUser() { defer drv.Close() client := NewClient(Driver(drv)) // creating vertices for the user's edges. + c0 := client.Car. + Create(). + SaveX(ctx) + log.Println("car created:", c0) // create user vertex with its edges. u := client.User. @@ -92,10 +119,16 @@ func ExampleUser() { SetNewName("string"). SetBlob(nil). SetState(user.StateLoggedIn). + AddCar(c0). SaveX(ctx) log.Println("user created:", u) // query edges. + c0, err = u.QueryCar().First(ctx) + if err != nil { + log.Fatalf("failed querying car: %v", err) + } + log.Println("car found:", c0) // Output: } diff --git a/entc/integration/migrate/entv2/migrate/schema.go b/entc/integration/migrate/entv2/migrate/schema.go index 7f715a342..3703ffc5d 100644 --- a/entc/integration/migrate/entv2/migrate/schema.go +++ b/entc/integration/migrate/entv2/migrate/schema.go @@ -14,6 +14,26 @@ import ( ) var ( + // CarsColumns holds the columns for the "cars" table. + CarsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "owner_id", Type: field.TypeInt, Nullable: true}, + } + // CarsTable holds the schema information for the "cars" table. + CarsTable = &schema.Table{ + Name: "cars", + Columns: CarsColumns, + PrimaryKey: []*schema.Column{CarsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "cars_users_car", + Columns: []*schema.Column{CarsColumns[1]}, + + RefColumns: []*schema.Column{UsersColumns[0]}, + OnDelete: schema.SetNull, + }, + }, + } // GroupsColumns holds the columns for the "groups" table. GroupsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -65,6 +85,7 @@ var ( } // Tables holds all the tables in the schema. Tables = []*schema.Table{ + CarsTable, GroupsTable, PetsTable, UsersTable, @@ -72,4 +93,5 @@ var ( ) func init() { + CarsTable.ForeignKeys[0].RefTable = UsersTable } diff --git a/entc/integration/migrate/entv2/predicate/predicate.go b/entc/integration/migrate/entv2/predicate/predicate.go index 8b5bcc6d5..575e37992 100644 --- a/entc/integration/migrate/entv2/predicate/predicate.go +++ b/entc/integration/migrate/entv2/predicate/predicate.go @@ -10,6 +10,9 @@ import ( "github.com/facebookincubator/ent/dialect/sql" ) +// Car is the predicate function for car builders. +type Car func(*sql.Selector) + // Group is the predicate function for group builders. type Group func(*sql.Selector) diff --git a/entc/integration/migrate/entv2/schema/user.go b/entc/integration/migrate/entv2/schema/user.go index bf4daead8..17e551227 100644 --- a/entc/integration/migrate/entv2/schema/user.go +++ b/entc/integration/migrate/entv2/schema/user.go @@ -6,6 +6,7 @@ package schema import ( "github.com/facebookincubator/ent" + "github.com/facebookincubator/ent/schema/edge" "github.com/facebookincubator/ent/schema/field" "github.com/facebookincubator/ent/schema/index" ) @@ -51,6 +52,14 @@ func (User) Fields() []ent.Field { } } +func (User) Edges() []ent.Edge { + return []ent.Edge{ + // Edge(children<-M2O->parent) to be dropped. + // Edge(spouse<-O2O->spouse) to be dropped. + edge.To("car", Car.Type), + } +} + func (User) Indexes() []ent.Index { return []ent.Index{ // deleting old indexes (name, address), @@ -60,6 +69,19 @@ func (User) Indexes() []ent.Index { } } +type Car struct { + ent.Schema +} + +func (Car) Edges() []ent.Edge { + return []ent.Edge{ + // Car now can have more than 1 owner (not unique anymore). + edge.From("owner", User.Type). + Ref("car"). + Unique(), + } +} + // Additional types to be added to the schema. type ( // Pet schema. diff --git a/entc/integration/migrate/entv2/tx.go b/entc/integration/migrate/entv2/tx.go index 8b9e95caf..b568beb8b 100644 --- a/entc/integration/migrate/entv2/tx.go +++ b/entc/integration/migrate/entv2/tx.go @@ -16,6 +16,8 @@ import ( // Tx is a transactional client that is created by calling Client.Tx(). type Tx struct { config + // Car is the client for interacting with the Car builders. + Car *CarClient // Group is the client for interacting with the Group builders. Group *GroupClient // Pet is the client for interacting with the Pet builders. @@ -39,6 +41,7 @@ func (tx *Tx) Client() *Client { return &Client{ config: tx.config, Schema: migrate.NewSchema(tx.driver), + Car: NewCarClient(tx.config), Group: NewGroupClient(tx.config), Pet: NewPetClient(tx.config), User: NewUserClient(tx.config), @@ -52,7 +55,7 @@ func (tx *Tx) Client() *Client { // of them in order to commit or rollback the transaction. // // If a closed transaction is embedded in one of the generated entities, and the entity -// applies a query, for example: Group.QueryXXX(), the query will be executed +// applies a query, for example: Car.QueryXXX(), the query will be executed // through the driver which created this transaction. // // Note that txDriver is not goroutine safe. diff --git a/entc/integration/migrate/entv2/user.go b/entc/integration/migrate/entv2/user.go index 517efeeee..387d50b24 100644 --- a/entc/integration/migrate/entv2/user.go +++ b/entc/integration/migrate/entv2/user.go @@ -115,6 +115,11 @@ func (u *User) assignValues(values ...interface{}) error { return nil } +// QueryCar queries the car edge of the User. +func (u *User) QueryCar() *CarQuery { + return (&UserClient{u.config}).QueryCar(u) +} + // Update returns a builder for updating this User. // Note that, you need to call User.Unwrap() before calling this method, if this User // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/entc/integration/migrate/entv2/user/user.go b/entc/integration/migrate/entv2/user/user.go index 3d6a66d29..62c886d04 100644 --- a/entc/integration/migrate/entv2/user/user.go +++ b/entc/integration/migrate/entv2/user/user.go @@ -38,6 +38,13 @@ const ( // Table holds the table name of the user in the database. Table = "users" + // CarTable is the table the holds the car relation/edge. + CarTable = "cars" + // CarInverseTable is the table name for the Car entity. + // It exists in this package in order to avoid circular dependency with the "car" package. + CarInverseTable = "cars" + // CarColumn is the table column denoting the car relation/edge. + CarColumn = "owner_id" ) // Columns holds all SQL columns are user fields. diff --git a/entc/integration/migrate/entv2/user/where.go b/entc/integration/migrate/entv2/user/where.go index 93117c83e..afa132072 100644 --- a/entc/integration/migrate/entv2/user/where.go +++ b/entc/integration/migrate/entv2/user/where.go @@ -8,6 +8,7 @@ package user import ( "github.com/facebookincubator/ent/dialect/sql" + "github.com/facebookincubator/ent/dialect/sql/sqlgraph" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" ) @@ -1156,6 +1157,36 @@ func StateNotNil() predicate.User { ) } +// HasCar applies the HasEdge predicate on the "car" edge. +func HasCar() predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(CarTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, CarTable, CarColumn), + ) + sqlgraph.HasNeighbors(s, step) + }, + ) +} + +// HasCarWith applies the HasEdge predicate on the "car" edge with a given conditions (other predicates). +func HasCarWith(preds ...predicate.Car) predicate.User { + return predicate.User(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(CarInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, CarTable, CarColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }, + ) +} + // And groups list of predicates with the AND operator between them. func And(predicates ...predicate.User) predicate.User { return predicate.User( diff --git a/entc/integration/migrate/entv2/user_create.go b/entc/integration/migrate/entv2/user_create.go index 13b943c97..1f50965cc 100644 --- a/entc/integration/migrate/entv2/user_create.go +++ b/entc/integration/migrate/entv2/user_create.go @@ -12,6 +12,7 @@ import ( "fmt" "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" "github.com/facebookincubator/ent/schema/field" ) @@ -28,6 +29,7 @@ type UserCreate struct { new_name *string blob *[]byte state *user.State + car map[int]struct{} } // SetAge sets the age field. @@ -116,6 +118,26 @@ func (uc *UserCreate) SetNillableState(u *user.State) *UserCreate { return uc } +// AddCarIDs adds the car edge to Car by ids. +func (uc *UserCreate) AddCarIDs(ids ...int) *UserCreate { + if uc.car == nil { + uc.car = make(map[int]struct{}) + } + for i := range ids { + uc.car[ids[i]] = struct{}{} + } + return uc +} + +// AddCar adds the car edges to Car. +func (uc *UserCreate) AddCar(c ...*Car) *UserCreate { + ids := make([]int, len(c)) + for i := range c { + ids[i] = c[i].ID + } + return uc.AddCarIDs(ids...) +} + // Save creates the User in the database. func (uc *UserCreate) Save(ctx context.Context) (*User, error) { if uc.age == nil { @@ -235,6 +257,25 @@ func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) { }) u.State = *value } + if nodes := uc.car; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges = append(spec.Edges, edge) + } if err := sqlgraph.CreateNode(ctx, uc.driver, spec); err != nil { if cerr, ok := isSQLConstraintError(err); ok { err = cerr diff --git a/entc/integration/migrate/entv2/user_query.go b/entc/integration/migrate/entv2/user_query.go index 54c729d64..886d1bfed 100644 --- a/entc/integration/migrate/entv2/user_query.go +++ b/entc/integration/migrate/entv2/user_query.go @@ -14,6 +14,7 @@ import ( "github.com/facebookincubator/ent/dialect/sql" "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" "github.com/facebookincubator/ent/schema/field" @@ -55,6 +56,18 @@ func (uq *UserQuery) Order(o ...Order) *UserQuery { return uq } +// QueryCar chains the current query on the car edge. +func (uq *UserQuery) QueryCar() *CarQuery { + query := &CarQuery{config: uq.config} + step := sqlgraph.NewStep( + sqlgraph.From(user.Table, user.FieldID, uq.sqlQuery()), + sqlgraph.To(car.Table, car.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, user.CarTable, user.CarColumn), + ) + query.sql = sqlgraph.SetNeighbors(uq.driver.Dialect(), step) + return query +} + // First returns the first User entity in the query. Returns *ErrNotFound when no user was found. func (uq *UserQuery) First(ctx context.Context) (*User, error) { us, err := uq.Limit(1).All(ctx) diff --git a/entc/integration/migrate/entv2/user_update.go b/entc/integration/migrate/entv2/user_update.go index d69b61c86..cebf3fc34 100644 --- a/entc/integration/migrate/entv2/user_update.go +++ b/entc/integration/migrate/entv2/user_update.go @@ -12,6 +12,7 @@ import ( "github.com/facebookincubator/ent/dialect/sql" "github.com/facebookincubator/ent/dialect/sql/sqlgraph" + "github.com/facebookincubator/ent/entc/integration/migrate/entv2/car" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/predicate" "github.com/facebookincubator/ent/entc/integration/migrate/entv2/user" "github.com/facebookincubator/ent/schema/field" @@ -34,6 +35,8 @@ type UserUpdate struct { clearblob bool state *user.State clearstate bool + car map[int]struct{} + removedCar map[int]struct{} predicates []predicate.User } @@ -168,6 +171,46 @@ func (uu *UserUpdate) ClearState() *UserUpdate { return uu } +// AddCarIDs adds the car edge to Car by ids. +func (uu *UserUpdate) AddCarIDs(ids ...int) *UserUpdate { + if uu.car == nil { + uu.car = make(map[int]struct{}) + } + for i := range ids { + uu.car[ids[i]] = struct{}{} + } + return uu +} + +// AddCar adds the car edges to Car. +func (uu *UserUpdate) AddCar(c ...*Car) *UserUpdate { + ids := make([]int, len(c)) + for i := range c { + ids[i] = c[i].ID + } + return uu.AddCarIDs(ids...) +} + +// RemoveCarIDs removes the car edge to Car by ids. +func (uu *UserUpdate) RemoveCarIDs(ids ...int) *UserUpdate { + if uu.removedCar == nil { + uu.removedCar = make(map[int]struct{}) + } + for i := range ids { + uu.removedCar[ids[i]] = struct{}{} + } + return uu +} + +// RemoveCar removes car edges to Car. +func (uu *UserUpdate) RemoveCar(c ...*Car) *UserUpdate { + ids := make([]int, len(c)) + for i := range c { + ids[i] = c[i].ID + } + return uu.RemoveCarIDs(ids...) +} + // Save executes the query and returns the number of rows/vertices matched by this operation. func (uu *UserUpdate) Save(ctx context.Context) (int, error) { if uu.state != nil { @@ -312,6 +355,44 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: user.FieldState, }) } + if nodes := uu.removedCar; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uu.car; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + 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, uu.driver, spec); err != nil { if cerr, ok := isSQLConstraintError(err); ok { err = cerr @@ -339,6 +420,8 @@ type UserUpdateOne struct { clearblob bool state *user.State clearstate bool + car map[int]struct{} + removedCar map[int]struct{} } // SetAge sets the age field. @@ -466,6 +549,46 @@ func (uuo *UserUpdateOne) ClearState() *UserUpdateOne { return uuo } +// AddCarIDs adds the car edge to Car by ids. +func (uuo *UserUpdateOne) AddCarIDs(ids ...int) *UserUpdateOne { + if uuo.car == nil { + uuo.car = make(map[int]struct{}) + } + for i := range ids { + uuo.car[ids[i]] = struct{}{} + } + return uuo +} + +// AddCar adds the car edges to Car. +func (uuo *UserUpdateOne) AddCar(c ...*Car) *UserUpdateOne { + ids := make([]int, len(c)) + for i := range c { + ids[i] = c[i].ID + } + return uuo.AddCarIDs(ids...) +} + +// RemoveCarIDs removes the car edge to Car by ids. +func (uuo *UserUpdateOne) RemoveCarIDs(ids ...int) *UserUpdateOne { + if uuo.removedCar == nil { + uuo.removedCar = make(map[int]struct{}) + } + for i := range ids { + uuo.removedCar[ids[i]] = struct{}{} + } + return uuo +} + +// RemoveCar removes car edges to Car. +func (uuo *UserUpdateOne) RemoveCar(c ...*Car) *UserUpdateOne { + ids := make([]int, len(c)) + for i := range c { + ids[i] = c[i].ID + } + return uuo.RemoveCarIDs(ids...) +} + // Save executes the query and returns the updated entity. func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { if uuo.state != nil { @@ -604,6 +727,44 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) { Column: user.FieldState, }) } + if nodes := uuo.removedCar; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Clear = append(spec.Edges.Clear, edge) + } + if nodes := uuo.car; len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: user.CarTable, + Columns: []string{user.CarColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: car.FieldID, + }, + }, + } + for k, _ := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + spec.Edges.Add = append(spec.Edges.Add, edge) + } u = &User{config: uuo.config} spec.Assign = u.assignValues spec.ScanValues = u.scanValues() diff --git a/entc/integration/migrate/migrate_test.go b/entc/integration/migrate/migrate_test.go index eafb69187..e39db041f 100644 --- a/entc/integration/migrate/migrate_test.go +++ b/entc/integration/migrate/migrate_test.go @@ -81,9 +81,10 @@ func TestSQLite(t *testing.T) { require.NoError(t, client.Schema.Create(ctx, migratev2.WithGlobalUniqueID(true))) SanityV2(t, client) - idRange(t, client.Group.Create().SaveX(ctx).ID, 0, 1<<32) - idRange(t, client.Pet.Create().SaveX(ctx).ID, 1<<32-1, 2<<32) - idRange(t, client.User.Create().SetAge(1).SetName("x").SetNickname("x'").SetPhone("y").SaveX(ctx).ID, 2<<32, 3<<32-1) + idRange(t, client.Car.Create().SaveX(ctx).ID, 0, 1<<32) + idRange(t, client.Group.Create().SaveX(ctx).ID, 1<<32-1, 2<<32) + idRange(t, client.Pet.Create().SaveX(ctx).ID, 2<<32-1, 3<<32) + idRange(t, client.User.Create().SetAge(1).SetName("x").SetNickname("x'").SetPhone("y").SaveX(ctx).ID, 3<<32-1, 4<<32) // override the default behavior of LIKE in SQLite. // https://www.sqlite.org/pragma.html#pragma_case_sensitive_like @@ -106,9 +107,10 @@ func V1ToV2(t *testing.T, clientv1 *entv1.Client, clientv2 *entv2.Client) { // since "users" created in the migration of v1, it will occupy the range of 0 ... 1<<32-1, // even though they are ordered differently in the migration of v2 (groups, pets, users). - idRange(t, clientv2.User.Create().SetAge(1).SetName("foo").SetNickname("nick_foo").SetPhone("phone").SaveX(ctx).ID, 0, 1<<32) - idRange(t, clientv2.Group.Create().SaveX(ctx).ID, 1<<32-1, 2<<32) - idRange(t, clientv2.Pet.Create().SaveX(ctx).ID, 2<<32-1, 3<<32) + idRange(t, clientv2.Car.Create().SaveX(ctx).ID, 0, 1<<32) + idRange(t, clientv2.User.Create().SetAge(1).SetName("foo").SetNickname("nick_foo").SetPhone("phone").SaveX(ctx).ID, 1<<32-1, 2<<32) + idRange(t, clientv2.Group.Create().SaveX(ctx).ID, 2<<32-1, 3<<32) + idRange(t, clientv2.Pet.Create().SaveX(ctx).ID, 3<<32-1, 4<<32) // sql specific predicates. EqualFold(t, clientv2)