ent/field: add update_default option time field

Reviewed By: alexsn

Differential Revision: D17070907

fbshipit-source-id: 63c9ce75c58e524044c38f9461cb04e8e45c8017
This commit is contained in:
Ariel Mashraki
2019-08-27 06:53:44 -07:00
committed by Facebook Github Bot
parent bd07c86b60
commit 772b8a33f8
30 changed files with 376 additions and 100 deletions

File diff suppressed because one or more lines are too long

View File

@@ -26,9 +26,9 @@ type {{ $builder }} struct {
// Save creates the {{ $.Name }} in the database.
func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (*{{ $.Name }}, error) {
{{ range $_, $f := $.Fields -}}
{{- if or $f.HasDefault (not $f.Optional) -}}
{{- if or $f.Default (not $f.Optional) -}}
if {{ $receiver }}.{{ $f.StructField }} == nil {
{{ if $f.HasDefault -}}
{{ if $f.Default -}}
v := {{ $.Package }}.{{ $f.DefaultName }}{{ if $f.IsTime }}(){{ end }}
{{ $receiver }}.{{ $f.StructField }} = &v
{{ else -}}
@@ -38,7 +38,7 @@ func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (*{{ $.Name }},
{{ end -}}
{{ with $f.Validators -}}
{{/* add nullable check only for optional fields without default value */ -}}
{{ $nullable := and $f.Optional (not $f.HasDefault) -}}
{{ $nullable := and $f.Optional (not $f.Default) -}}
{{- if $nullable }} if {{ $receiver }}.{{ $f.StructField }} != nil { {{ end -}}
if err := {{ $.Package }}.{{ $f.Validator }}(*{{ $receiver }}.{{ $f.StructField }}); err != nil {
return nil, fmt.Errorf("{{ $pkg }}: validator failed for field \"{{ $f.Name }}\": %v", err)

View File

@@ -2,7 +2,9 @@
{{ $builder := pascal $.Scope.Builder }}
{{ $receiver := receiver $builder }}
{{ $fields := $.Fields }}
{{ $updater := false }}
{{- if or (hasSuffix $builder "Update") (hasSuffix $builder "UpdateOne") }}
{{ $updater := true }}
{{ $fields = $.MutableFields }}
{{- end }}
@@ -15,7 +17,7 @@
return {{ $receiver }}
}
{{/* avoid generting nillable setters for slices because the nil value for slice is valid */}}
{{ if and (not $f.Type.Slice) (or $f.Optional $f.Nillable $f.HasDefault) }}
{{ if and (not $f.Type.Slice) (or $f.Optional $f.Default) (not (and $updater $f.UpdateDefault)) }}
{{ $nillableFunc := print "SetNillable" (pascal $f.Name) }}
// {{ $nillableFunc }} sets the {{ $f.Name }} field if the given value is not nil.
func ({{ $receiver }} *{{ $builder }}) {{ $nillableFunc }}({{ $p }} *{{ $f.Type }}) *{{ $builder }} {

View File

@@ -33,7 +33,7 @@ func ({{ $receiver}} *{{ $builder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $b
// Save executes the query and returns the number of rows/vertices matched by this operation.
func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (int, error) {
{{ with extend $ "Receiver" $receiver "Package" $pkg "ZeroValue" 0 -}}
{{ template "update/validators" . }}
{{ template "update/save" . }}
{{- end -}}
{{- if $multistorage -}}
switch {{ $receiver }}.driver.Dialect() {
@@ -100,7 +100,7 @@ type {{ $onebuilder }} struct {
// Save executes the query and returns the updated entity.
func ({{ $receiver }} *{{ $onebuilder }} ) Save(ctx context.Context) (*{{ $.Name }}, error) {
{{ with extend $ "Receiver" $receiver "Package" $pkg "ZeroValue" "nil" -}}
{{ template "update/validators" . }}
{{ template "update/save" . }}
{{- end -}}
{{- if $multistorage -}}
switch {{ $receiver }}.driver.Dialect() {
@@ -149,8 +149,10 @@ func ({{ $receiver }} *{{ $onebuilder }}) ExecX(ctx context.Context) {
{{/* shared struct fields between the two updaters */}}
{{ define "update/fields"}}
{{ range $_, $f := $.MutableFields }}
{{- $f.StructField }} *{{ $f.Type }}
{{ range $_, $f := $.Fields }}
{{- if or (not $f.Immutable) $f.UpdateDefault }}
{{- $f.StructField }} *{{ $f.Type }}
{{- end }}
{{ end }}
{{- range $_, $e := $.Edges }}
{{- $e.StructField }} map[{{ $.ID.Type }}]struct{}
@@ -203,12 +205,18 @@ func ({{ $receiver }} *{{ $onebuilder }}) ExecX(ctx context.Context) {
{{ end }}
{{ end }}
{{/* shared templates for validators. */}}
{{ define "update/validators" }}
{{/* shared template for the save method of the 2 builders */}}
{{ define "update/save" }}
{{- $pkg := .Scope.Package -}}
{{- $zero := .Scope.ZeroValue }}
{{- $receiver := .Scope.Receiver -}}
{{- range $_, $f := $.Fields -}}
{{- if $f.UpdateDefault -}}
if {{ $receiver }}.{{ $f.StructField }} == nil {
v := {{ $.Package }}.{{ $f.UpdateDefaultName }}{{ if $f.IsTime }}(){{ end }}
{{ $receiver }}.{{ $f.StructField }} = &v
}
{{ end -}}
{{ with $f.Validators -}}
if {{ $receiver }}.{{ $f.StructField }} != nil {
if err := {{ $.Package }}.{{ $f.Validator }}(*{{ $receiver }}.{{ $f.StructField }}); err != nil {

View File

@@ -49,7 +49,7 @@ func ({{ $receiver }} *{{ $slice }}) FromResponse(res *gremlin.Response) error {
*{{ $receiver }} = append(*{{ $receiver }}, &{{ $.Name }}{
ID: v.ID,
{{ range $_, $f := $.Fields }}
{{- pascal $f.Name }}: {{- if $f.IsTime }}time.Unix(v.{{ pascal $f.Name }}, 0) {{ else }}v.{{ pascal $f.Name }}{{ end }},
{{- pascal $f.Name }}: {{- if $f.IsTime }}time.Unix(0, v.{{ pascal $f.Name }}) {{ else }}v.{{ pascal $f.Name }}{{ end }},
{{ end -}}
})
}

View File

@@ -50,16 +50,18 @@ func ({{ $receiver }} *{{ $builder }}) gremlin({{ if $one }}id {{ $.ID.Type }}{{
{{ end }}
trs []*dsl.Traversal
)
{{- range $_, $f := $.MutableFields }}
if {{ $receiver }}.{{ $f.StructField }} != nil {
{{- if $f.Unique }}
constraints = append(constraints, &constraint{
pred: g.V().Has({{ $.Package }}.Label, {{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }}).Count(),
test: __.Is(p.NEQ(0)).Constant(NewErrUniqueField({{ $.Package }}.Label, {{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }})),
})
{{- range $_, $f := $.Fields }}
{{- if or (not $f.Immutable) $f.UpdateDefault }}
if {{ $receiver }}.{{ $f.StructField }} != nil {
{{- if $f.Unique }}
constraints = append(constraints, &constraint{
pred: g.V().Has({{ $.Package }}.Label, {{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }}).Count(),
test: __.Is(p.NEQ(0)).Constant(NewErrUniqueField({{ $.Package }}.Label, {{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }})),
})
{{- end }}
v.Property(dsl.Single, {{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }})
}
{{- end }}
v.Property(dsl.Single, {{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }})
}
{{- end }}
{{- range $_, $e := $.Edges }}
{{- $direction := "In" }}

View File

@@ -60,18 +60,20 @@ func ({{ $receiver }} *{{ $builder }}) sqlSave(ctx context.Context) ({{ $ret }}
res sql.Result
builder = sql.Update({{ $.Package }}.Table).Where(sql.InInts({{ $.Package }}.{{ $.ID.Constant }}, ids...))
)
{{- range $_, $f := $.MutableFields }}
if {{ $receiver }}.{{ $f.StructField }} != nil {
update = true
builder.Set({{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }})
{{- if $one }}
{{- if $f.Nillable }}
{{ $.Receiver }}.{{ pascal $f.Name }} = {{ $receiver }}.{{ $f.StructField }}
{{- else }}
{{ $.Receiver }}.{{ pascal $f.Name }} = *{{ $receiver }}.{{ $f.StructField }}
{{- range $_, $f := $.Fields }}
{{- if or (not $f.Immutable) $f.UpdateDefault }}
if {{ $receiver }}.{{ $f.StructField }} != nil {
update = true
builder.Set({{ $.Package }}.{{ $f.Constant }}, *{{ $receiver }}.{{ $f.StructField }})
{{- if $one }}
{{- if $f.Nillable }}
{{ $.Receiver }}.{{ pascal $f.Name }} = {{ $receiver }}.{{ $f.StructField }}
{{- else }}
{{ $.Receiver }}.{{ pascal $f.Name }} = *{{ $receiver }}.{{ $f.StructField }}
{{- end }}
{{- end }}
{{- end }}
}
}
{{- end }}
{{- end }}
if update {
query, args := builder.Query()

View File

@@ -33,15 +33,20 @@ var (
fields = {{ base $.Schema }}.{{ $.Name }}{}.Fields()
{{ range $i, $f := $.Fields -}}
{{- $desc := print "desc" (pascal $f.Name) -}}
{{ if or $f.HasDefault $f.Validators -}}
{{ if or $f.Default $f.UpdateDefault $f.Validators -}}
// {{ $desc }} is the schema descriptor for {{ $f.Name }} field.
{{ $desc }} = fields[{{ $i }}].Descriptor()
{{ end -}}
{{ if $f.HasDefault }}
{{ if $f.Default }}
{{- $default := $f.DefaultName -}}
// {{ $default }} holds the default value for the {{ $f.Name }} field.
// {{ $default }} holds the default value on creation for the {{ $f.Name }} field.
{{ $default }} = {{ $desc }}.Default.({{ if $f.IsTime }}func() {{ end }}{{ $f.Type }})
{{ end -}}
{{ if $f.UpdateDefault }}
{{- $default := $f.UpdateDefaultName -}}
// {{ $default }} holds the default value on update for the {{ $f.Name }} field.
{{ $default }} = {{ $desc }}.UpdateDefault.({{ if $f.IsTime }}func() {{ end }}{{ $f.Type }})
{{ end -}}
{{ with $f.Validators -}}
{{ $name := $f.Validator -}}
{{ $type := printf "func (%s) error" $f.Type -}}

View File

@@ -52,8 +52,10 @@ type (
// Nillable indicates that this field can be null in the
// database and pointer in the generated entities.
Nillable bool
// HasDefault indicates if this field a default value.
HasDefault bool
// Default indicates if this field has a default value for creation.
Default bool
// UpdateDefault indicates if this field has a default value for update.
UpdateDefault bool
// Immutable indicates is this field cannot be updated.
Immutable bool
// StructTag of the field. default to "json".
@@ -142,16 +144,17 @@ func NewType(c Config, schema *load.Schema) (*Type, error) {
return nil, fmt.Errorf("field %q redeclared for type %q", f.Name, typ.Name)
}
typ.Fields[i] = &Field{
def: f,
Name: f.Name,
Type: f.Type,
Unique: f.Unique,
Nillable: f.Nillable,
Optional: f.Optional,
HasDefault: f.Default,
Immutable: f.Immutable,
StructTag: structTag(f.Name, f.Tag),
Validators: f.Validators,
def: f,
Name: f.Name,
Type: f.Type,
Unique: f.Unique,
Nillable: f.Nillable,
Optional: f.Optional,
Default: f.Default,
UpdateDefault: f.UpdateDefault,
Immutable: f.Immutable,
StructTag: structTag(f.Name, f.Tag),
Validators: f.Validators,
}
typ.fields[f.Name] = typ.Fields[i]
}
@@ -194,10 +197,20 @@ func (t Type) HasValidators() bool {
return false
}
// HasDefault indicates if any of this type's fields has default value.
// HasDefault indicates if any of this type's fields has default value on creation.
func (t Type) HasDefault() bool {
for _, f := range t.Fields {
if f.HasDefault {
if f.Default {
return true
}
}
return false
}
// HasUpdateDefault indicates if any of this type's fields has default value on update.
func (t Type) HasUpdateDefault() bool {
for _, f := range t.Fields {
if f.Default {
return true
}
}
@@ -331,6 +344,9 @@ func (f Field) Constant() string { return "Field" + pascal(f.Name) }
// DefaultName returns the variable name of the default value of this field.
func (f Field) DefaultName() string { return "Default" + pascal(f.Name) }
// UpdateDefaultName returns the variable name of the update default value of this field.
func (f Field) UpdateDefaultName() string { return "Update" + f.DefaultName() }
// StructField returns the struct member of the field.
func (f Field) StructField() string {
if token.Lookup(f.Name).IsKeyword() {
@@ -404,7 +420,7 @@ func (f Field) Column() *schema.Column {
c.Charset = *f.def.Charset
}
}
if f.HasDefault && !f.IsTime() {
if f.Default && !f.IsTime() {
// since this column is used only for codegen, the actual default
// value is imported by the migrate package and used directly.
c.Default = true

View File

@@ -21,6 +21,8 @@ type Card struct {
Number string `json:"number,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
// FromRows scans the sql response data into Card.
@@ -29,18 +31,21 @@ func (c *Card) FromRows(rows *sql.Rows) error {
ID int
Number sql.NullString
CreatedAt sql.NullTime
UpdatedAt sql.NullTime
}
// the order here should be the same as in the `card.Columns`.
if err := rows.Scan(
&vc.ID,
&vc.Number,
&vc.CreatedAt,
&vc.UpdatedAt,
); err != nil {
return err
}
c.ID = strconv.Itoa(vc.ID)
c.Number = vc.Number.String
c.CreatedAt = vc.CreatedAt.Time
c.UpdatedAt = vc.UpdatedAt.Time
return nil
}
@@ -54,6 +59,7 @@ func (c *Card) FromResponse(res *gremlin.Response) error {
ID string `json:"id,omitempty"`
Number string `json:"number,omitempty"`
CreatedAt int64 `json:"created_at,omitempty"`
UpdatedAt int64 `json:"updated_at,omitempty"`
}
if err := vmap.Decode(&vc); err != nil {
return err
@@ -61,6 +67,7 @@ func (c *Card) FromResponse(res *gremlin.Response) error {
c.ID = vc.ID
c.Number = vc.Number
c.CreatedAt = time.Unix(vc.CreatedAt, 0)
c.UpdatedAt = time.Unix(vc.UpdatedAt, 0)
return nil
}
@@ -94,6 +101,7 @@ func (c *Card) String() string {
buf.WriteString(fmt.Sprintf("id=%v", c.ID))
buf.WriteString(fmt.Sprintf(", number=%v", c.Number))
buf.WriteString(fmt.Sprintf(", created_at=%v", c.CreatedAt))
buf.WriteString(fmt.Sprintf(", updated_at=%v", c.UpdatedAt))
buf.WriteString(")")
return buf.String()
}
@@ -129,6 +137,7 @@ func (c *Cards) FromResponse(res *gremlin.Response) error {
ID string `json:"id,omitempty"`
Number string `json:"number,omitempty"`
CreatedAt int64 `json:"created_at,omitempty"`
UpdatedAt int64 `json:"updated_at,omitempty"`
}
if err := vmap.Decode(&vc); err != nil {
return err
@@ -137,7 +146,8 @@ func (c *Cards) FromResponse(res *gremlin.Response) error {
*c = append(*c, &Card{
ID: v.ID,
Number: v.Number,
CreatedAt: time.Unix(v.CreatedAt, 0),
CreatedAt: time.Unix(0, v.CreatedAt),
UpdatedAt: time.Unix(0, v.UpdatedAt),
})
}
return nil

View File

@@ -17,6 +17,8 @@ const (
FieldNumber = "number"
// FieldCreatedAt holds the string denoting the created_at vertex property in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at vertex property in the database.
FieldUpdatedAt = "updated_at"
// Table holds the table name of the card in the database.
Table = "cards"
@@ -37,6 +39,7 @@ var Columns = []string{
FieldID,
FieldNumber,
FieldCreatedAt,
FieldUpdatedAt,
}
var (
@@ -47,6 +50,12 @@ var (
NumberValidator = descNumber.Validators[0].(func(string) error)
// descCreatedAt is the schema descriptor for created_at field.
descCreatedAt = fields[1].Descriptor()
// DefaultCreatedAt holds the default value for the created_at field.
// DefaultCreatedAt holds the default value on creation for the created_at field.
DefaultCreatedAt = descCreatedAt.Default.(func() time.Time)
// descUpdatedAt is the schema descriptor for updated_at field.
descUpdatedAt = fields[2].Descriptor()
// DefaultUpdatedAt holds the default value on creation for the updated_at field.
DefaultUpdatedAt = descUpdatedAt.Default.(func() time.Time)
// UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
UpdateDefaultUpdatedAt = descUpdatedAt.UpdateDefault.(func() time.Time)
)

View File

@@ -181,6 +181,18 @@ func CreatedAt(v time.Time) predicate.Card {
)
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.EQ(v))
},
)
}
// NumberEQ applies the EQ predicate on the "number" field.
func NumberEQ(v string) predicate.Card {
return predicate.CardPerDialect(
@@ -449,6 +461,122 @@ func CreatedAtNotIn(vs ...time.Time) predicate.Card {
)
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.EQ(v))
},
)
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.NEQ(v))
},
)
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.GT(v))
},
)
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.GTE(v))
},
)
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.LT(v))
},
)
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.Card {
return predicate.CardPerDialect(
func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldUpdatedAt), v))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.LTE(v))
},
)
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.Card {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.CardPerDialect(
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(vs) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldUpdatedAt), v...))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.Within(v...))
},
)
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.Card {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.CardPerDialect(
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(vs) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldUpdatedAt), v...))
},
func(t *dsl.Traversal) {
t.Has(Label, FieldUpdatedAt, p.Without(v...))
},
)
}
// HasOwner applies the HasEdge predicate on the "owner" edge.
func HasOwner() predicate.Card {
return predicate.CardPerDialect(

View File

@@ -26,6 +26,7 @@ type CardCreate struct {
config
number *string
created_at *time.Time
updated_at *time.Time
owner map[string]struct{}
}
@@ -49,6 +50,20 @@ func (cc *CardCreate) SetNillableCreatedAt(t *time.Time) *CardCreate {
return cc
}
// SetUpdatedAt sets the updated_at field.
func (cc *CardCreate) SetUpdatedAt(t time.Time) *CardCreate {
cc.updated_at = &t
return cc
}
// SetNillableUpdatedAt sets the updated_at field if the given value is not nil.
func (cc *CardCreate) SetNillableUpdatedAt(t *time.Time) *CardCreate {
if t != nil {
cc.SetUpdatedAt(*t)
}
return cc
}
// SetOwnerID sets the owner edge to User by id.
func (cc *CardCreate) SetOwnerID(id string) *CardCreate {
if cc.owner == nil {
@@ -83,6 +98,10 @@ func (cc *CardCreate) Save(ctx context.Context) (*Card, error) {
v := card.DefaultCreatedAt()
cc.created_at = &v
}
if cc.updated_at == nil {
v := card.DefaultUpdatedAt()
cc.updated_at = &v
}
if len(cc.owner) > 1 {
return nil, errors.New("ent: multiple assignments on a unique edge \"owner\"")
}
@@ -123,6 +142,10 @@ func (cc *CardCreate) sqlSave(ctx context.Context) (*Card, error) {
builder.Set(card.FieldCreatedAt, *cc.created_at)
c.CreatedAt = *cc.created_at
}
if cc.updated_at != nil {
builder.Set(card.FieldUpdatedAt, *cc.updated_at)
c.UpdatedAt = *cc.updated_at
}
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
return nil, rollback(tx, err)
@@ -187,6 +210,9 @@ func (cc *CardCreate) gremlin() *dsl.Traversal {
if cc.created_at != nil {
v.Property(dsl.Single, card.FieldCreatedAt, *cc.created_at)
}
if cc.updated_at != nil {
v.Property(dsl.Single, card.FieldUpdatedAt, *cc.updated_at)
}
for id := range cc.owner {
v.AddE(user.CardLabel).From(g.V(id)).InV()
constraints = append(constraints, &constraint{

View File

@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"strconv"
"time"
"github.com/facebookincubator/ent/entc/integration/ent/card"
"github.com/facebookincubator/ent/entc/integration/ent/predicate"
@@ -24,7 +25,9 @@ import (
// CardUpdate is the builder for updating Card entities.
type CardUpdate struct {
config
number *string
number *string
updated_at *time.Time
owner map[string]struct{}
clearedOwner bool
predicates []predicate.Card
@@ -77,6 +80,10 @@ func (cu *CardUpdate) Save(ctx context.Context) (int, error) {
return 0, fmt.Errorf("ent: validator failed for field \"number\": %v", err)
}
}
if cu.updated_at == nil {
v := card.UpdateDefaultUpdatedAt()
cu.updated_at = &v
}
if len(cu.owner) > 1 {
return 0, errors.New("ent: multiple assignments on a unique edge \"owner\"")
}
@@ -148,6 +155,10 @@ func (cu *CardUpdate) sqlSave(ctx context.Context) (n int, err error) {
update = true
builder.Set(card.FieldNumber, *cu.number)
}
if cu.updated_at != nil {
update = true
builder.Set(card.FieldUpdatedAt, *cu.updated_at)
}
if update {
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
@@ -222,6 +233,9 @@ func (cu *CardUpdate) gremlin() *dsl.Traversal {
if cu.number != nil {
v.Property(dsl.Single, card.FieldNumber, *cu.number)
}
if cu.updated_at != nil {
v.Property(dsl.Single, card.FieldUpdatedAt, *cu.updated_at)
}
if cu.clearedOwner {
tr := rv.Clone().InE(user.CardLabel).Drop().Iterate()
trs = append(trs, tr)
@@ -251,8 +265,10 @@ func (cu *CardUpdate) gremlin() *dsl.Traversal {
// CardUpdateOne is the builder for updating a single Card entity.
type CardUpdateOne struct {
config
id string
number *string
id string
number *string
updated_at *time.Time
owner map[string]struct{}
clearedOwner bool
}
@@ -298,6 +314,10 @@ func (cuo *CardUpdateOne) Save(ctx context.Context) (*Card, error) {
return nil, fmt.Errorf("ent: validator failed for field \"number\": %v", err)
}
}
if cuo.updated_at == nil {
v := card.UpdateDefaultUpdatedAt()
cuo.updated_at = &v
}
if len(cuo.owner) > 1 {
return nil, errors.New("ent: multiple assignments on a unique edge \"owner\"")
}
@@ -373,6 +393,11 @@ func (cuo *CardUpdateOne) sqlSave(ctx context.Context) (c *Card, err error) {
builder.Set(card.FieldNumber, *cuo.number)
c.Number = *cuo.number
}
if cuo.updated_at != nil {
update = true
builder.Set(card.FieldUpdatedAt, *cuo.updated_at)
c.UpdatedAt = *cuo.updated_at
}
if update {
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
@@ -448,6 +473,9 @@ func (cuo *CardUpdateOne) gremlin(id string) *dsl.Traversal {
if cuo.number != nil {
v.Property(dsl.Single, card.FieldNumber, *cuo.number)
}
if cuo.updated_at != nil {
v.Property(dsl.Single, card.FieldUpdatedAt, *cuo.updated_at)
}
if cuo.clearedOwner {
tr := rv.Clone().InE(user.CardLabel).Drop().Iterate()
trs = append(trs, tr)

View File

@@ -34,6 +34,7 @@ func ExampleCard() {
Create().
SetNumber("string").
SetCreatedAt(time.Now()).
SetUpdatedAt(time.Now()).
SaveX(ctx)
log.Println("card created:", c)
@@ -342,6 +343,7 @@ func ExampleUser() {
Create().
SetNumber("string").
SetCreatedAt(time.Now()).
SetUpdatedAt(time.Now()).
SaveX(ctx)
log.Println("card created:", c0)
pe1 := client.Pet.

View File

@@ -56,7 +56,7 @@ var (
fields = schema.File{}.Fields()
// descSize is the schema descriptor for size field.
descSize = fields[0].Descriptor()
// DefaultSize holds the default value for the size field.
// DefaultSize holds the default value on creation for the size field.
DefaultSize = descSize.Default.(int)
// SizeValidator is a validator for the "size" field. It is called by the builders before save.
SizeValidator = descSize.Validators[0].(func(int) error)

View File

@@ -184,7 +184,7 @@ func (gr *Groups) FromResponse(res *gremlin.Response) error {
*gr = append(*gr, &Group{
ID: v.ID,
Active: v.Active,
Expire: time.Unix(v.Expire, 0),
Expire: time.Unix(0, v.Expire),
Type: v.Type,
MaxUsers: v.MaxUsers,
Name: v.Name,

View File

@@ -81,7 +81,7 @@ var (
fields = schema.Group{}.Fields()
// descActive is the schema descriptor for active field.
descActive = fields[0].Descriptor()
// DefaultActive holds the default value for the active field.
// DefaultActive holds the default value on creation for the active field.
DefaultActive = descActive.Default.(bool)
// descType is the schema descriptor for type field.
descType = fields[2].Descriptor()
@@ -89,7 +89,7 @@ var (
TypeValidator = descType.Validators[0].(func(string) error)
// descMaxUsers is the schema descriptor for max_users field.
descMaxUsers = fields[3].Descriptor()
// DefaultMaxUsers holds the default value for the max_users field.
// DefaultMaxUsers holds the default value on creation for the max_users field.
DefaultMaxUsers = descMaxUsers.Default.(int)
// MaxUsersValidator is a validator for the "max_users" field. It is called by the builders before save.
MaxUsersValidator = descMaxUsers.Validators[0].(func(int) error)

View File

@@ -41,6 +41,6 @@ var (
fields = schema.GroupInfo{}.Fields()
// descMaxUsers is the schema descriptor for max_users field.
descMaxUsers = fields[1].Descriptor()
// DefaultMaxUsers holds the default value for the max_users field.
// DefaultMaxUsers holds the default value on creation for the max_users field.
DefaultMaxUsers = descMaxUsers.Default.(int)
)

View File

@@ -17,6 +17,7 @@ var (
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "number", Type: field.TypeString},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "owner_id", Type: field.TypeInt, Unique: true, Nullable: true},
}
// CardsTable holds the schema information for the "cards" table.
@@ -27,7 +28,7 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "cards_users_card",
Columns: []*schema.Column{CardsColumns[3]},
Columns: []*schema.Column{CardsColumns[4]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.SetNull,

View File

@@ -25,6 +25,10 @@ func (Card) Fields() []ent.Field {
field.Time("created_at").
Default(time.Now).
Immutable(),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now).
Immutable(),
}
}

View File

@@ -129,6 +129,6 @@ var (
fields = schema.User{}.Fields()
// descLast is the schema descriptor for last field.
descLast = fields[2].Descriptor()
// DefaultLast holds the default value for the last field.
// DefaultLast holds the default value on creation for the last field.
DefaultLast = descLast.Default.(string)
)

View File

@@ -1861,6 +1861,12 @@ func DefaultValue(t *testing.T, client *ent.Client) {
ctx := context.Background()
c1 := client.Card.Create().SetNumber("102030").SaveX(ctx)
require.False(t, c1.CreatedAt.IsZero())
require.False(t, c1.UpdatedAt.IsZero())
require.Equal(t, c1.UpdatedAt.Unix(), c1.CreatedAt.Unix())
c1 = c1.Update().SetNumber("302010").SaveX(ctx)
require.False(t, c1.CreatedAt.IsZero())
require.False(t, c1.UpdatedAt.IsZero())
require.NotEqual(t, c1.UpdatedAt.UnixNano(), c1.CreatedAt.UnixNano())
}
func ImmutableValue(t *testing.T, client *ent.Client) {

View File

@@ -40,10 +40,10 @@ var (
fields = schema.User{}.Fields()
// descBuffer is the schema descriptor for buffer field.
descBuffer = fields[3].Descriptor()
// DefaultBuffer holds the default value for the buffer field.
// DefaultBuffer holds the default value on creation for the buffer field.
DefaultBuffer = descBuffer.Default.([]byte)
// descTitle is the schema descriptor for title field.
descTitle = fields[4].Descriptor()
// DefaultTitle holds the default value for the title field.
// DefaultTitle holds the default value on creation for the title field.
DefaultTitle = descTitle.Default.(string)
)

File diff suppressed because one or more lines are too long

View File

@@ -25,17 +25,18 @@ type Schema struct {
// Field represents an ent.Field that was loaded from a complied user package.
type Field struct {
Name string `json:"name,omitempty"`
Type field.Type `json:"type,omitempty"`
Tag string `json:"tag,omitempty"`
Size *int `json:"size,omitempty"`
Charset *string `json:"charset,omitempty"`
Unique bool `json:"unique,omitempty"`
Nillable bool `json:"nillable,omitempty"`
Optional bool `json:"optional,omitempty"`
Default bool `json:"default,omitempty"`
Immutable bool `json:"immutable,omitempty"`
Validators int `json:"validators,omitempty"`
Name string `json:"name,omitempty"`
Type field.Type `json:"type,omitempty"`
Tag string `json:"tag,omitempty"`
Size *int `json:"size,omitempty"`
Charset *string `json:"charset,omitempty"`
Unique bool `json:"unique,omitempty"`
Nillable bool `json:"nillable,omitempty"`
Optional bool `json:"optional,omitempty"`
Default bool `json:"default,omitempty"`
UpdateDefault bool `json:"update_default,omitempty"`
Immutable bool `json:"immutable,omitempty"`
Validators int `json:"validators,omitempty"`
}
// Edge represents an ent.Edge that was loaded from a complied user package.
@@ -85,15 +86,16 @@ func MarshalSchema(schema ent.Interface) (b []byte, err error) {
for _, f := range fields {
fd := f.Descriptor()
sf := &Field{
Name: fd.Name,
Type: fd.Type,
Tag: fd.Tag,
Unique: fd.Unique,
Default: fd.Default != nil,
Nillable: fd.Nillable,
Optional: fd.Optional,
Immutable: fd.Immutable,
Validators: len(fd.Validators),
Name: fd.Name,
Type: fd.Type,
Tag: fd.Tag,
Unique: fd.Unique,
Nillable: fd.Nillable,
Optional: fd.Optional,
Immutable: fd.Immutable,
Validators: len(fd.Validators),
Default: fd.Default != nil,
UpdateDefault: fd.UpdateDefault != nil,
}
if fd.Size != 0 {
sf.Size = &fd.Size

View File

@@ -8,6 +8,7 @@ import (
"encoding/json"
"math"
"testing"
"time"
"github.com/facebookincubator/ent"
"github.com/facebookincubator/ent/schema/edge"
@@ -138,6 +139,8 @@ func (WithDefaults) Fields() []ent.Field {
Default("foo"),
field.Bool("string").
Default(true),
field.Time("updated_at").
UpdateDefault(time.Now),
}
}
@@ -163,4 +166,6 @@ func TestMarshalDefaults(t *testing.T) {
require.True(t, schema.Fields[1].Default)
require.True(t, schema.Fields[2].Default)
require.True(t, schema.Fields[3].Default)
require.False(t, schema.Fields[4].Default)
require.True(t, schema.Fields[4].UpdateDefault)
}