diff --git a/dialect/sql/schema/postgres.go b/dialect/sql/schema/postgres.go index 2c9e3b7e18..4a7a92d391 100644 --- a/dialect/sql/schema/postgres.go +++ b/dialect/sql/schema/postgres.go @@ -737,10 +737,10 @@ func (d *Postgres) atTypeC(c1 *Column, c2 *schema.Column) error { } func (d *Postgres) atUniqueC(t1 *Table, c1 *Column, t2 *schema.Table, c2 *schema.Column) { - // For UNIQUE columns, PostgreSQL create an implicit index named + // For UNIQUE columns, PostgreSQL creates an implicit index named // "__key". for _, idx := range t1.Indexes { - // Index also defined explicitly, and will be add in atIndexes. + // Index also defined explicitly, and will be added in atIndexes. if idx.Unique && d.atImplicitIndexName(idx, t1, c1) { return } diff --git a/entc/integration/migrate/entv2/customtype.go b/entc/integration/migrate/entv2/customtype.go index c36e05ae90..7b6b0e1c98 100644 --- a/entc/integration/migrate/entv2/customtype.go +++ b/entc/integration/migrate/entv2/customtype.go @@ -9,6 +9,7 @@ package entv2 import ( "fmt" "strings" + "time" "entgo.io/ent/dialect/sql" "entgo.io/ent/entc/integration/migrate/entv2/customtype" @@ -21,6 +22,10 @@ type CustomType struct { ID int `json:"id,omitempty"` // Custom holds the value of the "custom" field. Custom string `json:"custom,omitempty"` + // Tz0 holds the value of the "tz0" field. + Tz0 time.Time `json:"tz0,omitempty"` + // Tz3 holds the value of the "tz3" field. + Tz3 time.Time `json:"tz3,omitempty"` } // scanValues returns the types for scanning values from sql.Rows. @@ -32,6 +37,8 @@ func (*CustomType) scanValues(columns []string) ([]interface{}, error) { values[i] = new(sql.NullInt64) case customtype.FieldCustom: values[i] = new(sql.NullString) + case customtype.FieldTz0, customtype.FieldTz3: + values[i] = new(sql.NullTime) default: return nil, fmt.Errorf("unexpected column %q for type CustomType", columns[i]) } @@ -59,6 +66,18 @@ func (ct *CustomType) assignValues(columns []string, values []interface{}) error } else if value.Valid { ct.Custom = value.String } + case customtype.FieldTz0: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field tz0", values[i]) + } else if value.Valid { + ct.Tz0 = value.Time + } + case customtype.FieldTz3: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field tz3", values[i]) + } else if value.Valid { + ct.Tz3 = value.Time + } } } return nil @@ -89,6 +108,10 @@ func (ct *CustomType) String() string { builder.WriteString(fmt.Sprintf("id=%v", ct.ID)) builder.WriteString(", custom=") builder.WriteString(ct.Custom) + builder.WriteString(", tz0=") + builder.WriteString(ct.Tz0.Format(time.ANSIC)) + builder.WriteString(", tz3=") + builder.WriteString(ct.Tz3.Format(time.ANSIC)) builder.WriteByte(')') return builder.String() } diff --git a/entc/integration/migrate/entv2/customtype/customtype.go b/entc/integration/migrate/entv2/customtype/customtype.go index 6f50c12d4e..e8579e43be 100644 --- a/entc/integration/migrate/entv2/customtype/customtype.go +++ b/entc/integration/migrate/entv2/customtype/customtype.go @@ -13,6 +13,10 @@ const ( FieldID = "id" // FieldCustom holds the string denoting the custom field in the database. FieldCustom = "custom" + // FieldTz0 holds the string denoting the tz0 field in the database. + FieldTz0 = "tz0" + // FieldTz3 holds the string denoting the tz3 field in the database. + FieldTz3 = "tz3" // Table holds the table name of the customtype in the database. Table = "custom_types" ) @@ -21,6 +25,8 @@ const ( var Columns = []string{ FieldID, FieldCustom, + FieldTz0, + FieldTz3, } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/entc/integration/migrate/entv2/customtype/where.go b/entc/integration/migrate/entv2/customtype/where.go index 23b6cc00fd..c244fb284d 100644 --- a/entc/integration/migrate/entv2/customtype/where.go +++ b/entc/integration/migrate/entv2/customtype/where.go @@ -7,6 +7,8 @@ package customtype import ( + "time" + "entgo.io/ent/dialect/sql" "entgo.io/ent/entc/integration/migrate/entv2/predicate" ) @@ -101,6 +103,20 @@ func Custom(v string) predicate.CustomType { }) } +// Tz0 applies equality check predicate on the "tz0" field. It's identical to Tz0EQ. +func Tz0(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTz0), v)) + }) +} + +// Tz3 applies equality check predicate on the "tz3" field. It's identical to Tz3EQ. +func Tz3(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTz3), v)) + }) +} + // CustomEQ applies the EQ predicate on the "custom" field. func CustomEQ(v string) predicate.CustomType { return predicate.CustomType(func(s *sql.Selector) { @@ -226,6 +242,186 @@ func CustomContainsFold(v string) predicate.CustomType { }) } +// Tz0EQ applies the EQ predicate on the "tz0" field. +func Tz0EQ(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTz0), v)) + }) +} + +// Tz0NEQ applies the NEQ predicate on the "tz0" field. +func Tz0NEQ(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldTz0), v)) + }) +} + +// Tz0In applies the In predicate on the "tz0" field. +func Tz0In(vs ...time.Time) predicate.CustomType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.CustomType(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldTz0), v...)) + }) +} + +// Tz0NotIn applies the NotIn predicate on the "tz0" field. +func Tz0NotIn(vs ...time.Time) predicate.CustomType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.CustomType(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldTz0), v...)) + }) +} + +// Tz0GT applies the GT predicate on the "tz0" field. +func Tz0GT(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldTz0), v)) + }) +} + +// Tz0GTE applies the GTE predicate on the "tz0" field. +func Tz0GTE(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldTz0), v)) + }) +} + +// Tz0LT applies the LT predicate on the "tz0" field. +func Tz0LT(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldTz0), v)) + }) +} + +// Tz0LTE applies the LTE predicate on the "tz0" field. +func Tz0LTE(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldTz0), v)) + }) +} + +// Tz0IsNil applies the IsNil predicate on the "tz0" field. +func Tz0IsNil() predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldTz0))) + }) +} + +// Tz0NotNil applies the NotNil predicate on the "tz0" field. +func Tz0NotNil() predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldTz0))) + }) +} + +// Tz3EQ applies the EQ predicate on the "tz3" field. +func Tz3EQ(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTz3), v)) + }) +} + +// Tz3NEQ applies the NEQ predicate on the "tz3" field. +func Tz3NEQ(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldTz3), v)) + }) +} + +// Tz3In applies the In predicate on the "tz3" field. +func Tz3In(vs ...time.Time) predicate.CustomType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.CustomType(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldTz3), v...)) + }) +} + +// Tz3NotIn applies the NotIn predicate on the "tz3" field. +func Tz3NotIn(vs ...time.Time) predicate.CustomType { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.CustomType(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldTz3), v...)) + }) +} + +// Tz3GT applies the GT predicate on the "tz3" field. +func Tz3GT(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldTz3), v)) + }) +} + +// Tz3GTE applies the GTE predicate on the "tz3" field. +func Tz3GTE(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldTz3), v)) + }) +} + +// Tz3LT applies the LT predicate on the "tz3" field. +func Tz3LT(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldTz3), v)) + }) +} + +// Tz3LTE applies the LTE predicate on the "tz3" field. +func Tz3LTE(v time.Time) predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldTz3), v)) + }) +} + +// Tz3IsNil applies the IsNil predicate on the "tz3" field. +func Tz3IsNil() predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldTz3))) + }) +} + +// Tz3NotNil applies the NotNil predicate on the "tz3" field. +func Tz3NotNil() predicate.CustomType { + return predicate.CustomType(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldTz3))) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.CustomType) predicate.CustomType { return predicate.CustomType(func(s *sql.Selector) { diff --git a/entc/integration/migrate/entv2/customtype_create.go b/entc/integration/migrate/entv2/customtype_create.go index 9927fb8df4..bae326d9c2 100644 --- a/entc/integration/migrate/entv2/customtype_create.go +++ b/entc/integration/migrate/entv2/customtype_create.go @@ -9,6 +9,7 @@ package entv2 import ( "context" "fmt" + "time" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/entc/integration/migrate/entv2/customtype" @@ -36,6 +37,34 @@ func (ctc *CustomTypeCreate) SetNillableCustom(s *string) *CustomTypeCreate { return ctc } +// SetTz0 sets the "tz0" field. +func (ctc *CustomTypeCreate) SetTz0(t time.Time) *CustomTypeCreate { + ctc.mutation.SetTz0(t) + return ctc +} + +// SetNillableTz0 sets the "tz0" field if the given value is not nil. +func (ctc *CustomTypeCreate) SetNillableTz0(t *time.Time) *CustomTypeCreate { + if t != nil { + ctc.SetTz0(*t) + } + return ctc +} + +// SetTz3 sets the "tz3" field. +func (ctc *CustomTypeCreate) SetTz3(t time.Time) *CustomTypeCreate { + ctc.mutation.SetTz3(t) + return ctc +} + +// SetNillableTz3 sets the "tz3" field if the given value is not nil. +func (ctc *CustomTypeCreate) SetNillableTz3(t *time.Time) *CustomTypeCreate { + if t != nil { + ctc.SetTz3(*t) + } + return ctc +} + // Mutation returns the CustomTypeMutation object of the builder. func (ctc *CustomTypeCreate) Mutation() *CustomTypeMutation { return ctc.mutation @@ -141,6 +170,22 @@ func (ctc *CustomTypeCreate) createSpec() (*CustomType, *sqlgraph.CreateSpec) { }) _node.Custom = value } + if value, ok := ctc.mutation.Tz0(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: customtype.FieldTz0, + }) + _node.Tz0 = value + } + if value, ok := ctc.mutation.Tz3(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: customtype.FieldTz3, + }) + _node.Tz3 = value + } return _node, _spec } diff --git a/entc/integration/migrate/entv2/customtype_update.go b/entc/integration/migrate/entv2/customtype_update.go index 61bc0a8b3a..2bd4e9eb3d 100644 --- a/entc/integration/migrate/entv2/customtype_update.go +++ b/entc/integration/migrate/entv2/customtype_update.go @@ -10,6 +10,7 @@ import ( "context" "errors" "fmt" + "time" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" @@ -51,6 +52,46 @@ func (ctu *CustomTypeUpdate) ClearCustom() *CustomTypeUpdate { return ctu } +// SetTz0 sets the "tz0" field. +func (ctu *CustomTypeUpdate) SetTz0(t time.Time) *CustomTypeUpdate { + ctu.mutation.SetTz0(t) + return ctu +} + +// SetNillableTz0 sets the "tz0" field if the given value is not nil. +func (ctu *CustomTypeUpdate) SetNillableTz0(t *time.Time) *CustomTypeUpdate { + if t != nil { + ctu.SetTz0(*t) + } + return ctu +} + +// ClearTz0 clears the value of the "tz0" field. +func (ctu *CustomTypeUpdate) ClearTz0() *CustomTypeUpdate { + ctu.mutation.ClearTz0() + return ctu +} + +// SetTz3 sets the "tz3" field. +func (ctu *CustomTypeUpdate) SetTz3(t time.Time) *CustomTypeUpdate { + ctu.mutation.SetTz3(t) + return ctu +} + +// SetNillableTz3 sets the "tz3" field if the given value is not nil. +func (ctu *CustomTypeUpdate) SetNillableTz3(t *time.Time) *CustomTypeUpdate { + if t != nil { + ctu.SetTz3(*t) + } + return ctu +} + +// ClearTz3 clears the value of the "tz3" field. +func (ctu *CustomTypeUpdate) ClearTz3() *CustomTypeUpdate { + ctu.mutation.ClearTz3() + return ctu +} + // Mutation returns the CustomTypeMutation object of the builder. func (ctu *CustomTypeUpdate) Mutation() *CustomTypeMutation { return ctu.mutation @@ -141,6 +182,32 @@ func (ctu *CustomTypeUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: customtype.FieldCustom, }) } + if value, ok := ctu.mutation.Tz0(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: customtype.FieldTz0, + }) + } + if ctu.mutation.Tz0Cleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Column: customtype.FieldTz0, + }) + } + if value, ok := ctu.mutation.Tz3(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: customtype.FieldTz3, + }) + } + if ctu.mutation.Tz3Cleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Column: customtype.FieldTz3, + }) + } if n, err = sqlgraph.UpdateNodes(ctx, ctu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{customtype.Label} @@ -180,6 +247,46 @@ func (ctuo *CustomTypeUpdateOne) ClearCustom() *CustomTypeUpdateOne { return ctuo } +// SetTz0 sets the "tz0" field. +func (ctuo *CustomTypeUpdateOne) SetTz0(t time.Time) *CustomTypeUpdateOne { + ctuo.mutation.SetTz0(t) + return ctuo +} + +// SetNillableTz0 sets the "tz0" field if the given value is not nil. +func (ctuo *CustomTypeUpdateOne) SetNillableTz0(t *time.Time) *CustomTypeUpdateOne { + if t != nil { + ctuo.SetTz0(*t) + } + return ctuo +} + +// ClearTz0 clears the value of the "tz0" field. +func (ctuo *CustomTypeUpdateOne) ClearTz0() *CustomTypeUpdateOne { + ctuo.mutation.ClearTz0() + return ctuo +} + +// SetTz3 sets the "tz3" field. +func (ctuo *CustomTypeUpdateOne) SetTz3(t time.Time) *CustomTypeUpdateOne { + ctuo.mutation.SetTz3(t) + return ctuo +} + +// SetNillableTz3 sets the "tz3" field if the given value is not nil. +func (ctuo *CustomTypeUpdateOne) SetNillableTz3(t *time.Time) *CustomTypeUpdateOne { + if t != nil { + ctuo.SetTz3(*t) + } + return ctuo +} + +// ClearTz3 clears the value of the "tz3" field. +func (ctuo *CustomTypeUpdateOne) ClearTz3() *CustomTypeUpdateOne { + ctuo.mutation.ClearTz3() + return ctuo +} + // Mutation returns the CustomTypeMutation object of the builder. func (ctuo *CustomTypeUpdateOne) Mutation() *CustomTypeMutation { return ctuo.mutation @@ -294,6 +401,32 @@ func (ctuo *CustomTypeUpdateOne) sqlSave(ctx context.Context) (_node *CustomType Column: customtype.FieldCustom, }) } + if value, ok := ctuo.mutation.Tz0(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: customtype.FieldTz0, + }) + } + if ctuo.mutation.Tz0Cleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Column: customtype.FieldTz0, + }) + } + if value, ok := ctuo.mutation.Tz3(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: customtype.FieldTz3, + }) + } + if ctuo.mutation.Tz3Cleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Column: customtype.FieldTz3, + }) + } _node = &CustomType{config: ctuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/entc/integration/migrate/entv2/migrate/schema.go b/entc/integration/migrate/entv2/migrate/schema.go index 5d349c257a..f49f7c042c 100644 --- a/entc/integration/migrate/entv2/migrate/schema.go +++ b/entc/integration/migrate/entv2/migrate/schema.go @@ -56,6 +56,8 @@ var ( CustomTypesColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, {Name: "custom", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "customtype"}}, + {Name: "tz0", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "timestamp(0)", "postgres": "timestamptz(0)"}}, + {Name: "tz3", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "timestamp(3)", "postgres": "timestamptz(3)"}}, } // CustomTypesTable holds the schema information for the "custom_types" table. CustomTypesTable = &schema.Table{ diff --git a/entc/integration/migrate/entv2/mutation.go b/entc/integration/migrate/entv2/mutation.go index abf3e9092b..8a2e768b62 100644 --- a/entc/integration/migrate/entv2/mutation.go +++ b/entc/integration/migrate/entv2/mutation.go @@ -1368,6 +1368,8 @@ type CustomTypeMutation struct { typ string id *int custom *string + tz0 *time.Time + tz3 *time.Time clearedFields map[string]struct{} done bool oldValue func(context.Context) (*CustomType, error) @@ -1521,6 +1523,104 @@ func (m *CustomTypeMutation) ResetCustom() { delete(m.clearedFields, customtype.FieldCustom) } +// SetTz0 sets the "tz0" field. +func (m *CustomTypeMutation) SetTz0(t time.Time) { + m.tz0 = &t +} + +// Tz0 returns the value of the "tz0" field in the mutation. +func (m *CustomTypeMutation) Tz0() (r time.Time, exists bool) { + v := m.tz0 + if v == nil { + return + } + return *v, true +} + +// OldTz0 returns the old "tz0" field's value of the CustomType entity. +// If the CustomType object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CustomTypeMutation) OldTz0(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTz0 is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTz0 requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTz0: %w", err) + } + return oldValue.Tz0, nil +} + +// ClearTz0 clears the value of the "tz0" field. +func (m *CustomTypeMutation) ClearTz0() { + m.tz0 = nil + m.clearedFields[customtype.FieldTz0] = struct{}{} +} + +// Tz0Cleared returns if the "tz0" field was cleared in this mutation. +func (m *CustomTypeMutation) Tz0Cleared() bool { + _, ok := m.clearedFields[customtype.FieldTz0] + return ok +} + +// ResetTz0 resets all changes to the "tz0" field. +func (m *CustomTypeMutation) ResetTz0() { + m.tz0 = nil + delete(m.clearedFields, customtype.FieldTz0) +} + +// SetTz3 sets the "tz3" field. +func (m *CustomTypeMutation) SetTz3(t time.Time) { + m.tz3 = &t +} + +// Tz3 returns the value of the "tz3" field in the mutation. +func (m *CustomTypeMutation) Tz3() (r time.Time, exists bool) { + v := m.tz3 + if v == nil { + return + } + return *v, true +} + +// OldTz3 returns the old "tz3" field's value of the CustomType entity. +// If the CustomType object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CustomTypeMutation) OldTz3(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTz3 is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTz3 requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTz3: %w", err) + } + return oldValue.Tz3, nil +} + +// ClearTz3 clears the value of the "tz3" field. +func (m *CustomTypeMutation) ClearTz3() { + m.tz3 = nil + m.clearedFields[customtype.FieldTz3] = struct{}{} +} + +// Tz3Cleared returns if the "tz3" field was cleared in this mutation. +func (m *CustomTypeMutation) Tz3Cleared() bool { + _, ok := m.clearedFields[customtype.FieldTz3] + return ok +} + +// ResetTz3 resets all changes to the "tz3" field. +func (m *CustomTypeMutation) ResetTz3() { + m.tz3 = nil + delete(m.clearedFields, customtype.FieldTz3) +} + // Where appends a list predicates to the CustomTypeMutation builder. func (m *CustomTypeMutation) Where(ps ...predicate.CustomType) { m.predicates = append(m.predicates, ps...) @@ -1540,10 +1640,16 @@ func (m *CustomTypeMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *CustomTypeMutation) Fields() []string { - fields := make([]string, 0, 1) + fields := make([]string, 0, 3) if m.custom != nil { fields = append(fields, customtype.FieldCustom) } + if m.tz0 != nil { + fields = append(fields, customtype.FieldTz0) + } + if m.tz3 != nil { + fields = append(fields, customtype.FieldTz3) + } return fields } @@ -1554,6 +1660,10 @@ func (m *CustomTypeMutation) Field(name string) (ent.Value, bool) { switch name { case customtype.FieldCustom: return m.Custom() + case customtype.FieldTz0: + return m.Tz0() + case customtype.FieldTz3: + return m.Tz3() } return nil, false } @@ -1565,6 +1675,10 @@ func (m *CustomTypeMutation) OldField(ctx context.Context, name string) (ent.Val switch name { case customtype.FieldCustom: return m.OldCustom(ctx) + case customtype.FieldTz0: + return m.OldTz0(ctx) + case customtype.FieldTz3: + return m.OldTz3(ctx) } return nil, fmt.Errorf("unknown CustomType field %s", name) } @@ -1581,6 +1695,20 @@ func (m *CustomTypeMutation) SetField(name string, value ent.Value) error { } m.SetCustom(v) return nil + case customtype.FieldTz0: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTz0(v) + return nil + case customtype.FieldTz3: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTz3(v) + return nil } return fmt.Errorf("unknown CustomType field %s", name) } @@ -1614,6 +1742,12 @@ func (m *CustomTypeMutation) ClearedFields() []string { if m.FieldCleared(customtype.FieldCustom) { fields = append(fields, customtype.FieldCustom) } + if m.FieldCleared(customtype.FieldTz0) { + fields = append(fields, customtype.FieldTz0) + } + if m.FieldCleared(customtype.FieldTz3) { + fields = append(fields, customtype.FieldTz3) + } return fields } @@ -1631,6 +1765,12 @@ func (m *CustomTypeMutation) ClearField(name string) error { case customtype.FieldCustom: m.ClearCustom() return nil + case customtype.FieldTz0: + m.ClearTz0() + return nil + case customtype.FieldTz3: + m.ClearTz3() + return nil } return fmt.Errorf("unknown CustomType nullable field %s", name) } @@ -1642,6 +1782,12 @@ func (m *CustomTypeMutation) ResetField(name string) error { case customtype.FieldCustom: m.ResetCustom() return nil + case customtype.FieldTz0: + m.ResetTz0() + return nil + case customtype.FieldTz3: + m.ResetTz3() + return nil } return fmt.Errorf("unknown CustomType field %s", name) } diff --git a/entc/integration/migrate/entv2/schema/customtype.go b/entc/integration/migrate/entv2/schema/customtype.go index 9c28c53d80..c848af0a48 100644 --- a/entc/integration/migrate/entv2/schema/customtype.go +++ b/entc/integration/migrate/entv2/schema/customtype.go @@ -23,5 +23,17 @@ func (CustomType) Fields() []ent.Field { SchemaType(map[string]string{ dialect.Postgres: "customtype", }), + field.Time("tz0"). + Optional(). + SchemaType(map[string]string{ + dialect.MySQL: "timestamp(0)", + dialect.Postgres: "timestamptz(0)", + }), + field.Time("tz3"). + Optional(). + SchemaType(map[string]string{ + dialect.MySQL: "timestamp(3)", + dialect.Postgres: "timestamptz(3)", + }), } } diff --git a/entc/integration/migrate/migrate_test.go b/entc/integration/migrate/migrate_test.go index d1d39222c7..e76e303145 100644 --- a/entc/integration/migrate/migrate_test.go +++ b/entc/integration/migrate/migrate_test.go @@ -20,6 +20,7 @@ import ( userv1 "entgo.io/ent/entc/integration/migrate/entv1/user" "entgo.io/ent/entc/integration/migrate/entv2" "entgo.io/ent/entc/integration/migrate/entv2/conversion" + "entgo.io/ent/entc/integration/migrate/entv2/customtype" migratev2 "entgo.io/ent/entc/integration/migrate/entv2/migrate" "entgo.io/ent/entc/integration/migrate/entv2/user" @@ -52,6 +53,7 @@ func TestMySQL(t *testing.T) { CheckConstraint(t, clientv2) } NicknameSearch(t, clientv2) + TimePrecision(t, drv, "SELECT datetime_precision FROM information_schema.columns WHERE table_name = ? AND column_name = ?") }) } } @@ -81,6 +83,7 @@ func TestPostgres(t *testing.T) { clientv2 := entv2.NewClient(entv2.Driver(drv)) V1ToV2(t, drv.Dialect(), clientv1, clientv2) CheckConstraint(t, clientv2) + TimePrecision(t, drv, "SELECT datetime_precision FROM information_schema.columns WHERE table_name = $1 AND column_name = $2") }) } } @@ -381,6 +384,22 @@ func ContainsFold(t *testing.T, client *entv2.Client) { require.Equal(t, 1, client.User.Query().Where(user.NameContainsFold("Raki")).CountX(ctx)) } +func TimePrecision(t *testing.T, drv *sql.Driver, query string) { + ctx := context.Background() + rows, err := drv.QueryContext(ctx, query, customtype.Table, customtype.FieldTz0) + require.NoError(t, err) + p, err := sql.ScanInt(rows) + require.NoError(t, err) + require.Zerof(t, p, "custom_types field %q", customtype.FieldTz0) + require.NoError(t, rows.Close()) + rows, err = drv.QueryContext(ctx, query, customtype.Table, customtype.FieldTz3) + require.NoError(t, err) + p, err = sql.ScanInt(rows) + require.NoError(t, err) + require.Equalf(t, 3, p, "custom_types field %q", customtype.FieldTz3) + require.NoError(t, rows.Close()) +} + func idRange(t *testing.T, id, l, h int) { require.Truef(t, id > l && id < h, "id %s should be between %d to %d", id, l, h) } diff --git a/go.mod b/go.mod index ce9d2812d1..9c6d41baa9 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module entgo.io/ent go 1.17 require ( - ariga.io/atlas v0.3.8-0.20220324144249-d5d77d7dadfa + ariga.io/atlas v0.3.8-0.20220408073907-ec24677b8189 github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/go-openapi/inflect v0.19.0 github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index 5f33a2070f..fa39b3af4d 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,11 @@ ariga.io/atlas v0.3.8-0.20220324144249-d5d77d7dadfa h1:v+ZNqhCtR0uylXshIfghFGHTvpJrxB+9iNjWQV2UXak= ariga.io/atlas v0.3.8-0.20220324144249-d5d77d7dadfa/go.mod h1:2aAhlHuY8tr7rPNz2MgOBTJB/cVjK0sv1VvTIqeYSws= +ariga.io/atlas v0.3.8-0.20220407071148-7ea9876895d3 h1:2EhkjHhv8ICTFSRUaPdoKqfz4tPe21z875xjsaAKdBI= +ariga.io/atlas v0.3.8-0.20220407071148-7ea9876895d3/go.mod h1:2aAhlHuY8tr7rPNz2MgOBTJB/cVjK0sv1VvTIqeYSws= +ariga.io/atlas v0.3.8-0.20220407124003-f50cf4c884f2 h1:TpqxB+KZnOFbY/1qSLBNvT9/FmNhar6RhbkOUliJ6s4= +ariga.io/atlas v0.3.8-0.20220407124003-f50cf4c884f2/go.mod h1:2aAhlHuY8tr7rPNz2MgOBTJB/cVjK0sv1VvTIqeYSws= +ariga.io/atlas v0.3.8-0.20220408073907-ec24677b8189 h1:R8iwOEzgGDZtX9V96jtHId1fZL8sOyDtF3pdKt5uAQg= +ariga.io/atlas v0.3.8-0.20220408073907-ec24677b8189/go.mod h1:2aAhlHuY8tr7rPNz2MgOBTJB/cVjK0sv1VvTIqeYSws= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=