From 6c8a1308ec2d7a377b58eff15eb14eb99cfe4b18 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki <7413593+a8m@users.noreply.github.com> Date: Tue, 12 Jul 2022 18:13:45 +0300 Subject: [PATCH] entc/gen: edge schema with custom ids (#2742) Fixed https://github.com/ent/ent/issues/2740 Fixed https://github.com/ent/ent/issues/2741 --- dialect/sql/builder.go | 4 +- entc/gen/template/dialect/sql/entql.tmpl | 30 +- .../template/dialect/sql/feature/upsert.tmpl | 2 +- entc/integration/customid/customid_test.go | 6 + entc/integration/customid/ent/blob.go | 18 +- entc/integration/customid/ent/blob/blob.go | 9 + entc/integration/customid/ent/blob/where.go | 28 + entc/integration/customid/ent/blob_create.go | 4 + entc/integration/customid/ent/blob_query.go | 84 ++- entc/integration/customid/ent/blob_update.go | 24 + entc/integration/customid/ent/bloblink.go | 171 +++++ .../customid/ent/bloblink/bloblink.go | 66 ++ .../customid/ent/bloblink/where.go | 297 ++++++++ .../customid/ent/bloblink_create.go | 650 ++++++++++++++++++ .../customid/ent/bloblink_delete.go | 114 +++ .../customid/ent/bloblink_query.go | 584 ++++++++++++++++ .../customid/ent/bloblink_update.go | 550 +++++++++++++++ entc/integration/customid/ent/client.go | 96 +++ entc/integration/customid/ent/config.go | 1 + entc/integration/customid/ent/ent.go | 2 + entc/integration/customid/ent/entql.go | 193 +++++- entc/integration/customid/ent/generate.go | 2 +- entc/integration/customid/ent/hook/hook.go | 13 + .../customid/ent/migrate/schema.go | 57 +- entc/integration/customid/ent/mutation.go | 402 +++++++++++ .../customid/ent/predicate/predicate.go | 3 + .../customid/ent/privacy/privacy.go | 650 ++++++++++++++++++ entc/integration/customid/ent/runtime.go | 9 + entc/integration/customid/ent/schema/blob.go | 43 +- entc/integration/customid/ent/tx.go | 3 + .../integration/edgeschema/edgeschema_test.go | 1 + entc/integration/edgeschema/ent/client.go | 3 +- entc/integration/edgeschema/ent/runtime.go | 77 +-- .../edgeschema/ent/runtime/runtime.go | 90 ++- .../edgeschema/ent/schema/tweetlike.go | 13 + .../edgeschema/ent/tweetlike/tweetlike.go | 10 + .../edgeschema/ent/tweetlike_create.go | 10 +- .../edgeschema/ent/tweetlike_query.go | 7 + 38 files changed, 4162 insertions(+), 164 deletions(-) create mode 100644 entc/integration/customid/ent/bloblink.go create mode 100644 entc/integration/customid/ent/bloblink/bloblink.go create mode 100644 entc/integration/customid/ent/bloblink/where.go create mode 100644 entc/integration/customid/ent/bloblink_create.go create mode 100644 entc/integration/customid/ent/bloblink_delete.go create mode 100644 entc/integration/customid/ent/bloblink_query.go create mode 100644 entc/integration/customid/ent/bloblink_update.go create mode 100644 entc/integration/customid/ent/privacy/privacy.go diff --git a/dialect/sql/builder.go b/dialect/sql/builder.go index 709352a99..f8252775e 100644 --- a/dialect/sql/builder.go +++ b/dialect/sql/builder.go @@ -1535,8 +1535,8 @@ func In(col string, args ...interface{}) *Predicate { // In appends the `IN` predicate. func (p *Predicate) In(col string, args ...interface{}) *Predicate { - // if no arguments were provided, append the FALSE constants, - // since we can't apply "IN ()". This will make this predicate falsy. + // If no arguments were provided, append the FALSE constant, since + // we cannot apply "IN ()". This will make this predicate falsy. if len(args) == 0 { return p.False() } diff --git a/entc/gen/template/dialect/sql/entql.tmpl b/entc/gen/template/dialect/sql/entql.tmpl index b37a38316..3fa86fb69 100644 --- a/entc/gen/template/dialect/sql/entql.tmpl +++ b/entc/gen/template/dialect/sql/entql.tmpl @@ -31,10 +31,12 @@ var schemaGraph = func() *sqlgraph.Schema { NodeSpec: sqlgraph.NodeSpec{ Table: {{ $n.Package }}.Table, Columns: {{ $n.Package }}.Columns, - ID: &sqlgraph.FieldSpec{ - Type: field.{{ $n.ID.Type.ConstName }}, - Column: {{ $n.Package }}.{{ $n.ID.Constant }}, - }, + {{- if $n.HasOneFieldID }} + ID: &sqlgraph.FieldSpec{ + Type: field.{{ $n.ID.Type.ConstName }}, + Column: {{ $n.Package }}.{{ $n.ID.Constant }}, + }, + {{- end }} }, Type: "{{ $n.Name }}", Fields: map[string]*sqlgraph.FieldSpec{ @@ -110,16 +112,18 @@ type predicateAdder interface { }) } - {{ $type := $n.ID.Type.Type.String }} - {{ $iface := print (pascal $type) "P" }} - {{- if $n.ID.IsTime }}{{ $iface = "TimeP" }} - {{- else if or $n.ID.IsBytes $n.ID.IsJSON }}{{ $iface = "BytesP" }} - {{- else if $n.ID.IsUUID }}{{ $iface = "ValueP" }} + {{- if $n.HasOneFieldID }} + {{ $type := $n.ID.Type.Type.String }} + {{ $iface := print (pascal $type) "P" }} + {{- if $n.ID.IsTime }}{{ $iface = "TimeP" }} + {{- else if or $n.ID.IsBytes $n.ID.IsJSON }}{{ $iface = "BytesP" }} + {{- else if $n.ID.IsUUID }}{{ $iface = "ValueP" }} + {{- end }} + // WhereID applies the entql {{ $type }} predicate on the id field. + func (f *{{ $filter }}) WhereID(p entql.{{ $iface }}) { + f.Where(p.Field({{ $n.Package }}.{{ $n.ID.Constant }})) + } {{- end }} - // WhereID applies the entql {{ $type }} predicate on the id field. - func (f *{{ $filter }}) WhereID(p entql.{{ $iface }}) { - f.Where(p.Field({{ $n.Package }}.{{ $n.ID.Constant }})) - } {{ range $f := $n.Fields }} {{ $type := $f.Type.Type.String }} diff --git a/entc/gen/template/dialect/sql/feature/upsert.tmpl b/entc/gen/template/dialect/sql/feature/upsert.tmpl index 26f635761..49049ba34 100644 --- a/entc/gen/template/dialect/sql/feature/upsert.tmpl +++ b/entc/gen/template/dialect/sql/feature/upsert.tmpl @@ -335,7 +335,7 @@ func (u *{{ $upsertBulk }}) UpdateNewValues() *{{ $upsertBulk }} { {{- if or $udfID $.ImmutableFields }} u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { for _, b := range u.create.builders { - {{- if $.ID.UserDefined }} + {{- if $udfID }} if _, exists := b.mutation.ID(); exists { s.SetIgnore({{ $.Package }}.{{ $.ID.Constant }}) return diff --git a/entc/integration/customid/customid_test.go b/entc/integration/customid/customid_test.go index 313132176..c8c569890 100644 --- a/entc/integration/customid/customid_test.go +++ b/entc/integration/customid/customid_test.go @@ -116,6 +116,12 @@ func CustomID(t *testing.T, client *ent.Client) { require.Equal(t, lnk.ID, chd.QueryLinks().OnlyX(ctx).ID) require.Equal(t, lnk.ID, blb.QueryLinks().OnlyX(ctx).ID) require.Len(t, client.Blob.Query().IDsX(ctx), 3) + links := lnk.QueryBlobLinks().AllX(ctx) + require.Len(t, links, 2) + require.Equal(t, lnk.ID, links[0].BlobID) + require.NotEqual(t, uuid.Nil, links[0].LinkID) + require.Equal(t, lnk.ID, links[1].BlobID) + require.NotEqual(t, uuid.Nil, links[1].LinkID) pedro := client.Pet.Create().SetID("pedro").SetOwner(a8m).SaveX(ctx) require.Equal(t, a8m.ID, pedro.QueryOwner().OnlyIDX(ctx)) diff --git a/entc/integration/customid/ent/blob.go b/entc/integration/customid/ent/blob.go index f32c4adef..374ed3f01 100644 --- a/entc/integration/customid/ent/blob.go +++ b/entc/integration/customid/ent/blob.go @@ -36,9 +36,11 @@ type BlobEdges struct { Parent *Blob `json:"parent,omitempty"` // Links holds the value of the links edge. Links []*Blob `json:"links,omitempty"` + // BlobLinks holds the value of the blob_links edge. + BlobLinks []*BlobLink `json:"blob_links,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [3]bool } // ParentOrErr returns the Parent value or an error if the edge @@ -64,6 +66,15 @@ func (e BlobEdges) LinksOrErr() ([]*Blob, error) { return nil, &NotLoadedError{edge: "links"} } +// BlobLinksOrErr returns the BlobLinks value or an error if the edge +// was not loaded in eager-loading. +func (e BlobEdges) BlobLinksOrErr() ([]*BlobLink, error) { + if e.loadedTypes[2] { + return e.BlobLinks, nil + } + return nil, &NotLoadedError{edge: "blob_links"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Blob) scanValues(columns []string) ([]interface{}, error) { values := make([]interface{}, len(columns)) @@ -130,6 +141,11 @@ func (b *Blob) QueryLinks() *BlobQuery { return (&BlobClient{config: b.config}).QueryLinks(b) } +// QueryBlobLinks queries the "blob_links" edge of the Blob entity. +func (b *Blob) QueryBlobLinks() *BlobLinkQuery { + return (&BlobClient{config: b.config}).QueryBlobLinks(b) +} + // Update returns a builder for updating this Blob. // Note that you need to call Blob.Unwrap() before calling this method if this Blob // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/entc/integration/customid/ent/blob/blob.go b/entc/integration/customid/ent/blob/blob.go index 1b51d7ef7..07877964e 100644 --- a/entc/integration/customid/ent/blob/blob.go +++ b/entc/integration/customid/ent/blob/blob.go @@ -23,6 +23,8 @@ const ( EdgeParent = "parent" // EdgeLinks holds the string denoting the links edge name in mutations. EdgeLinks = "links" + // EdgeBlobLinks holds the string denoting the blob_links edge name in mutations. + EdgeBlobLinks = "blob_links" // Table holds the table name of the blob in the database. Table = "blobs" // ParentTable is the table that holds the parent relation/edge. @@ -31,6 +33,13 @@ const ( ParentColumn = "blob_parent" // LinksTable is the table that holds the links relation/edge. The primary key declared below. LinksTable = "blob_links" + // BlobLinksTable is the table that holds the blob_links relation/edge. + BlobLinksTable = "blob_links" + // BlobLinksInverseTable is the table name for the BlobLink entity. + // It exists in this package in order to avoid circular dependency with the "bloblink" package. + BlobLinksInverseTable = "blob_links" + // BlobLinksColumn is the table column denoting the blob_links relation/edge. + BlobLinksColumn = "blob_id" ) // Columns holds all SQL columns for blob fields. diff --git a/entc/integration/customid/ent/blob/where.go b/entc/integration/customid/ent/blob/where.go index a62cbfccb..b46fbc10f 100644 --- a/entc/integration/customid/ent/blob/where.go +++ b/entc/integration/customid/ent/blob/where.go @@ -306,6 +306,34 @@ func HasLinksWith(preds ...predicate.Blob) predicate.Blob { }) } +// HasBlobLinks applies the HasEdge predicate on the "blob_links" edge. +func HasBlobLinks() predicate.Blob { + return predicate.Blob(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(BlobLinksTable, BlobLinksColumn), + sqlgraph.Edge(sqlgraph.O2M, true, BlobLinksTable, BlobLinksColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasBlobLinksWith applies the HasEdge predicate on the "blob_links" edge with a given conditions (other predicates). +func HasBlobLinksWith(preds ...predicate.BlobLink) predicate.Blob { + return predicate.Blob(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(BlobLinksInverseTable, BlobLinksColumn), + sqlgraph.Edge(sqlgraph.O2M, true, BlobLinksTable, BlobLinksColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Blob) predicate.Blob { return predicate.Blob(func(s *sql.Selector) { diff --git a/entc/integration/customid/ent/blob_create.go b/entc/integration/customid/ent/blob_create.go index 166bb810b..38160eebc 100644 --- a/entc/integration/customid/ent/blob_create.go +++ b/entc/integration/customid/ent/blob_create.go @@ -292,6 +292,10 @@ func (bc *BlobCreate) createSpec() (*Blob, *sqlgraph.CreateSpec) { for _, k := range nodes { edge.Target.Nodes = append(edge.Target.Nodes, k) } + createE := &BlobLinkCreate{config: bc.config, mutation: newBlobLinkMutation(bc.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges = append(_spec.Edges, edge) } return _node, _spec diff --git a/entc/integration/customid/ent/blob_query.go b/entc/integration/customid/ent/blob_query.go index 29e85c8c2..3709258fd 100644 --- a/entc/integration/customid/ent/blob_query.go +++ b/entc/integration/customid/ent/blob_query.go @@ -15,6 +15,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" "entgo.io/ent/entc/integration/customid/ent/predicate" "entgo.io/ent/schema/field" "github.com/google/uuid" @@ -30,9 +31,10 @@ type BlobQuery struct { fields []string predicates []predicate.Blob // eager-loading edges. - withParent *BlobQuery - withLinks *BlobQuery - withFKs bool + withParent *BlobQuery + withLinks *BlobQuery + withBlobLinks *BlobLinkQuery + withFKs bool // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -113,6 +115,28 @@ func (bq *BlobQuery) QueryLinks() *BlobQuery { return query } +// QueryBlobLinks chains the current query on the "blob_links" edge. +func (bq *BlobQuery) QueryBlobLinks() *BlobLinkQuery { + query := &BlobLinkQuery{config: bq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := bq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := bq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(blob.Table, blob.FieldID, selector), + sqlgraph.To(bloblink.Table, bloblink.BlobColumn), + sqlgraph.Edge(sqlgraph.O2M, true, blob.BlobLinksTable, blob.BlobLinksColumn), + ) + fromU = sqlgraph.SetNeighbors(bq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Blob entity from the query. // Returns a *NotFoundError when no Blob was found. func (bq *BlobQuery) First(ctx context.Context) (*Blob, error) { @@ -289,13 +313,14 @@ func (bq *BlobQuery) Clone() *BlobQuery { return nil } return &BlobQuery{ - config: bq.config, - limit: bq.limit, - offset: bq.offset, - order: append([]OrderFunc{}, bq.order...), - predicates: append([]predicate.Blob{}, bq.predicates...), - withParent: bq.withParent.Clone(), - withLinks: bq.withLinks.Clone(), + config: bq.config, + limit: bq.limit, + offset: bq.offset, + order: append([]OrderFunc{}, bq.order...), + predicates: append([]predicate.Blob{}, bq.predicates...), + withParent: bq.withParent.Clone(), + withLinks: bq.withLinks.Clone(), + withBlobLinks: bq.withBlobLinks.Clone(), // clone intermediate query. sql: bq.sql.Clone(), path: bq.path, @@ -325,6 +350,17 @@ func (bq *BlobQuery) WithLinks(opts ...func(*BlobQuery)) *BlobQuery { return bq } +// WithBlobLinks tells the query-builder to eager-load the nodes that are connected to +// the "blob_links" edge. The optional arguments are used to configure the query builder of the edge. +func (bq *BlobQuery) WithBlobLinks(opts ...func(*BlobLinkQuery)) *BlobQuery { + query := &BlobLinkQuery{config: bq.config} + for _, opt := range opts { + opt(query) + } + bq.withBlobLinks = query + return bq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -396,9 +432,10 @@ func (bq *BlobQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Blob, e nodes = []*Blob{} withFKs = bq.withFKs _spec = bq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [3]bool{ bq.withParent != nil, bq.withLinks != nil, + bq.withBlobLinks != nil, } ) if bq.withParent != nil { @@ -508,6 +545,31 @@ func (bq *BlobQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Blob, e } } + if query := bq.withBlobLinks; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[uuid.UUID]*Blob) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + nodes[i].Edges.BlobLinks = []*BlobLink{} + } + query.Where(predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.InValues(blob.BlobLinksColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + fk := n.BlobID + node, ok := nodeids[fk] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "blob_id" returned %v for node %v`, fk, n) + } + node.Edges.BlobLinks = append(node.Edges.BlobLinks, n) + } + } + return nodes, nil } diff --git a/entc/integration/customid/ent/blob_update.go b/entc/integration/customid/ent/blob_update.go index cf3cdff7a..1b6c8373b 100644 --- a/entc/integration/customid/ent/blob_update.go +++ b/entc/integration/customid/ent/blob_update.go @@ -275,6 +275,10 @@ func (bu *BlobUpdate) sqlSave(ctx context.Context) (n int, err error) { }, }, } + createE := &BlobLinkCreate{config: bu.config, mutation: newBlobLinkMutation(bu.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges.Clear = append(_spec.Edges.Clear, edge) } if nodes := bu.mutation.RemovedLinksIDs(); len(nodes) > 0 && !bu.mutation.LinksCleared() { @@ -294,6 +298,10 @@ func (bu *BlobUpdate) sqlSave(ctx context.Context) (n int, err error) { for _, k := range nodes { edge.Target.Nodes = append(edge.Target.Nodes, k) } + createE := &BlobLinkCreate{config: bu.config, mutation: newBlobLinkMutation(bu.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges.Clear = append(_spec.Edges.Clear, edge) } if nodes := bu.mutation.LinksIDs(); len(nodes) > 0 { @@ -313,6 +321,10 @@ func (bu *BlobUpdate) sqlSave(ctx context.Context) (n int, err error) { for _, k := range nodes { edge.Target.Nodes = append(edge.Target.Nodes, k) } + createE := &BlobLinkCreate{config: bu.config, mutation: newBlobLinkMutation(bu.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges.Add = append(_spec.Edges.Add, edge) } if n, err = sqlgraph.UpdateNodes(ctx, bu.driver, _spec); err != nil { @@ -607,6 +619,10 @@ func (buo *BlobUpdateOne) sqlSave(ctx context.Context) (_node *Blob, err error) }, }, } + createE := &BlobLinkCreate{config: buo.config, mutation: newBlobLinkMutation(buo.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges.Clear = append(_spec.Edges.Clear, edge) } if nodes := buo.mutation.RemovedLinksIDs(); len(nodes) > 0 && !buo.mutation.LinksCleared() { @@ -626,6 +642,10 @@ func (buo *BlobUpdateOne) sqlSave(ctx context.Context) (_node *Blob, err error) for _, k := range nodes { edge.Target.Nodes = append(edge.Target.Nodes, k) } + createE := &BlobLinkCreate{config: buo.config, mutation: newBlobLinkMutation(buo.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges.Clear = append(_spec.Edges.Clear, edge) } if nodes := buo.mutation.LinksIDs(); len(nodes) > 0 { @@ -645,6 +665,10 @@ func (buo *BlobUpdateOne) sqlSave(ctx context.Context) (_node *Blob, err error) for _, k := range nodes { edge.Target.Nodes = append(edge.Target.Nodes, k) } + createE := &BlobLinkCreate{config: buo.config, mutation: newBlobLinkMutation(buo.config, OpCreate)} + createE.defaults() + _, specE := createE.createSpec() + edge.Target.Fields = specE.Fields _spec.Edges.Add = append(_spec.Edges.Add, edge) } _node = &Blob{config: buo.config} diff --git a/entc/integration/customid/ent/bloblink.go b/entc/integration/customid/ent/bloblink.go new file mode 100644 index 000000000..e1e7b6258 --- /dev/null +++ b/entc/integration/customid/ent/bloblink.go @@ -0,0 +1,171 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" + "github.com/google/uuid" +) + +// BlobLink is the model entity for the BlobLink schema. +type BlobLink struct { + config `json:"-"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // BlobID holds the value of the "blob_id" field. + BlobID uuid.UUID `json:"blob_id,omitempty"` + // LinkID holds the value of the "link_id" field. + LinkID uuid.UUID `json:"link_id,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the BlobLinkQuery when eager-loading is set. + Edges BlobLinkEdges `json:"edges"` +} + +// BlobLinkEdges holds the relations/edges for other nodes in the graph. +type BlobLinkEdges struct { + // Blob holds the value of the blob edge. + Blob *Blob `json:"blob,omitempty"` + // Link holds the value of the link edge. + Link *Blob `json:"link,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool +} + +// BlobOrErr returns the Blob value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e BlobLinkEdges) BlobOrErr() (*Blob, error) { + if e.loadedTypes[0] { + if e.Blob == nil { + // The edge blob was loaded in eager-loading, + // but was not found. + return nil, &NotFoundError{label: blob.Label} + } + return e.Blob, nil + } + return nil, &NotLoadedError{edge: "blob"} +} + +// LinkOrErr returns the Link value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e BlobLinkEdges) LinkOrErr() (*Blob, error) { + if e.loadedTypes[1] { + if e.Link == nil { + // The edge link was loaded in eager-loading, + // but was not found. + return nil, &NotFoundError{label: blob.Label} + } + return e.Link, nil + } + return nil, &NotLoadedError{edge: "link"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*BlobLink) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case bloblink.FieldCreatedAt: + values[i] = new(sql.NullTime) + case bloblink.FieldBlobID, bloblink.FieldLinkID: + values[i] = new(uuid.UUID) + default: + return nil, fmt.Errorf("unexpected column %q for type BlobLink", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the BlobLink fields. +func (bl *BlobLink) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case bloblink.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + bl.CreatedAt = value.Time + } + case bloblink.FieldBlobID: + if value, ok := values[i].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field blob_id", values[i]) + } else if value != nil { + bl.BlobID = *value + } + case bloblink.FieldLinkID: + if value, ok := values[i].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field link_id", values[i]) + } else if value != nil { + bl.LinkID = *value + } + } + } + return nil +} + +// QueryBlob queries the "blob" edge of the BlobLink entity. +func (bl *BlobLink) QueryBlob() *BlobQuery { + return (&BlobLinkClient{config: bl.config}).QueryBlob(bl) +} + +// QueryLink queries the "link" edge of the BlobLink entity. +func (bl *BlobLink) QueryLink() *BlobQuery { + return (&BlobLinkClient{config: bl.config}).QueryLink(bl) +} + +// Update returns a builder for updating this BlobLink. +// Note that you need to call BlobLink.Unwrap() before calling this method if this BlobLink +// was returned from a transaction, and the transaction was committed or rolled back. +func (bl *BlobLink) Update() *BlobLinkUpdateOne { + return (&BlobLinkClient{config: bl.config}).UpdateOne(bl) +} + +// Unwrap unwraps the BlobLink entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (bl *BlobLink) Unwrap() *BlobLink { + _tx, ok := bl.config.driver.(*txDriver) + if !ok { + panic("ent: BlobLink is not a transactional entity") + } + bl.config.driver = _tx.drv + return bl +} + +// String implements the fmt.Stringer. +func (bl *BlobLink) String() string { + var builder strings.Builder + builder.WriteString("BlobLink(") + builder.WriteString("created_at=") + builder.WriteString(bl.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("blob_id=") + builder.WriteString(fmt.Sprintf("%v", bl.BlobID)) + builder.WriteString(", ") + builder.WriteString("link_id=") + builder.WriteString(fmt.Sprintf("%v", bl.LinkID)) + builder.WriteByte(')') + return builder.String() +} + +// BlobLinks is a parsable slice of BlobLink. +type BlobLinks []*BlobLink + +func (bl BlobLinks) config(cfg config) { + for _i := range bl { + bl[_i].config = cfg + } +} diff --git a/entc/integration/customid/ent/bloblink/bloblink.go b/entc/integration/customid/ent/bloblink/bloblink.go new file mode 100644 index 000000000..c010de9b4 --- /dev/null +++ b/entc/integration/customid/ent/bloblink/bloblink.go @@ -0,0 +1,66 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package bloblink + +import ( + "time" +) + +const ( + // Label holds the string label denoting the bloblink type in the database. + Label = "blob_link" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldBlobID holds the string denoting the blob_id field in the database. + FieldBlobID = "blob_id" + // FieldLinkID holds the string denoting the link_id field in the database. + FieldLinkID = "link_id" + // EdgeBlob holds the string denoting the blob edge name in mutations. + EdgeBlob = "blob" + // EdgeLink holds the string denoting the link edge name in mutations. + EdgeLink = "link" + // BlobFieldID holds the string denoting the ID field of the Blob. + BlobFieldID = "id" + // Table holds the table name of the bloblink in the database. + Table = "blob_links" + // BlobTable is the table that holds the blob relation/edge. + BlobTable = "blob_links" + // BlobInverseTable is the table name for the Blob entity. + // It exists in this package in order to avoid circular dependency with the "blob" package. + BlobInverseTable = "blobs" + // BlobColumn is the table column denoting the blob relation/edge. + BlobColumn = "blob_id" + // LinkTable is the table that holds the link relation/edge. + LinkTable = "blob_links" + // LinkInverseTable is the table name for the Blob entity. + // It exists in this package in order to avoid circular dependency with the "blob" package. + LinkInverseTable = "blobs" + // LinkColumn is the table column denoting the link relation/edge. + LinkColumn = "link_id" +) + +// Columns holds all SQL columns for bloblink fields. +var Columns = []string{ + FieldCreatedAt, + FieldBlobID, + FieldLinkID, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time +) diff --git a/entc/integration/customid/ent/bloblink/where.go b/entc/integration/customid/ent/bloblink/where.go new file mode 100644 index 000000000..23b3f54f7 --- /dev/null +++ b/entc/integration/customid/ent/bloblink/where.go @@ -0,0 +1,297 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package bloblink + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/entc/integration/customid/ent/predicate" + "github.com/google/uuid" +) + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCreatedAt), v)) + }) +} + +// BlobID applies equality check predicate on the "blob_id" field. It's identical to BlobIDEQ. +func BlobID(v uuid.UUID) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldBlobID), v)) + }) +} + +// LinkID applies equality check predicate on the "link_id" field. It's identical to LinkIDEQ. +func LinkID(v uuid.UUID) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldLinkID), v)) + }) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.BlobLink { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.BlobLink(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(FieldCreatedAt), v...)) + }) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.BlobLink { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.BlobLink(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(FieldCreatedAt), v...)) + }) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldCreatedAt), v)) + }) +} + +// BlobIDEQ applies the EQ predicate on the "blob_id" field. +func BlobIDEQ(v uuid.UUID) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldBlobID), v)) + }) +} + +// BlobIDNEQ applies the NEQ predicate on the "blob_id" field. +func BlobIDNEQ(v uuid.UUID) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldBlobID), v)) + }) +} + +// BlobIDIn applies the In predicate on the "blob_id" field. +func BlobIDIn(vs ...uuid.UUID) predicate.BlobLink { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.BlobLink(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(FieldBlobID), v...)) + }) +} + +// BlobIDNotIn applies the NotIn predicate on the "blob_id" field. +func BlobIDNotIn(vs ...uuid.UUID) predicate.BlobLink { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.BlobLink(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(FieldBlobID), v...)) + }) +} + +// LinkIDEQ applies the EQ predicate on the "link_id" field. +func LinkIDEQ(v uuid.UUID) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldLinkID), v)) + }) +} + +// LinkIDNEQ applies the NEQ predicate on the "link_id" field. +func LinkIDNEQ(v uuid.UUID) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldLinkID), v)) + }) +} + +// LinkIDIn applies the In predicate on the "link_id" field. +func LinkIDIn(vs ...uuid.UUID) predicate.BlobLink { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.BlobLink(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(FieldLinkID), v...)) + }) +} + +// LinkIDNotIn applies the NotIn predicate on the "link_id" field. +func LinkIDNotIn(vs ...uuid.UUID) predicate.BlobLink { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.BlobLink(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(FieldLinkID), v...)) + }) +} + +// HasBlob applies the HasEdge predicate on the "blob" edge. +func HasBlob() predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, BlobColumn), + sqlgraph.To(BlobInverseTable, BlobFieldID), + sqlgraph.Edge(sqlgraph.M2O, false, BlobTable, BlobColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasBlobWith applies the HasEdge predicate on the "blob" edge with a given conditions (other predicates). +func HasBlobWith(preds ...predicate.Blob) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, BlobColumn), + sqlgraph.To(BlobInverseTable, BlobFieldID), + sqlgraph.Edge(sqlgraph.M2O, false, BlobTable, BlobColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasLink applies the HasEdge predicate on the "link" edge. +func HasLink() predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, LinkColumn), + sqlgraph.To(LinkInverseTable, BlobFieldID), + sqlgraph.Edge(sqlgraph.M2O, false, LinkTable, LinkColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasLinkWith applies the HasEdge predicate on the "link" edge with a given conditions (other predicates). +func HasLinkWith(preds ...predicate.Blob) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, LinkColumn), + sqlgraph.To(LinkInverseTable, BlobFieldID), + sqlgraph.Edge(sqlgraph.M2O, false, LinkTable, LinkColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.BlobLink) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.BlobLink) predicate.BlobLink { + return predicate.BlobLink(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.BlobLink) predicate.BlobLink { + return predicate.BlobLink(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/entc/integration/customid/ent/bloblink_create.go b/entc/integration/customid/ent/bloblink_create.go new file mode 100644 index 000000000..ba44e931b --- /dev/null +++ b/entc/integration/customid/ent/bloblink_create.go @@ -0,0 +1,650 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// BlobLinkCreate is the builder for creating a BlobLink entity. +type BlobLinkCreate struct { + config + mutation *BlobLinkMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (blc *BlobLinkCreate) SetCreatedAt(t time.Time) *BlobLinkCreate { + blc.mutation.SetCreatedAt(t) + return blc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (blc *BlobLinkCreate) SetNillableCreatedAt(t *time.Time) *BlobLinkCreate { + if t != nil { + blc.SetCreatedAt(*t) + } + return blc +} + +// SetBlobID sets the "blob_id" field. +func (blc *BlobLinkCreate) SetBlobID(u uuid.UUID) *BlobLinkCreate { + blc.mutation.SetBlobID(u) + return blc +} + +// SetLinkID sets the "link_id" field. +func (blc *BlobLinkCreate) SetLinkID(u uuid.UUID) *BlobLinkCreate { + blc.mutation.SetLinkID(u) + return blc +} + +// SetBlob sets the "blob" edge to the Blob entity. +func (blc *BlobLinkCreate) SetBlob(b *Blob) *BlobLinkCreate { + return blc.SetBlobID(b.ID) +} + +// SetLink sets the "link" edge to the Blob entity. +func (blc *BlobLinkCreate) SetLink(b *Blob) *BlobLinkCreate { + return blc.SetLinkID(b.ID) +} + +// Mutation returns the BlobLinkMutation object of the builder. +func (blc *BlobLinkCreate) Mutation() *BlobLinkMutation { + return blc.mutation +} + +// Save creates the BlobLink in the database. +func (blc *BlobLinkCreate) Save(ctx context.Context) (*BlobLink, error) { + var ( + err error + node *BlobLink + ) + blc.defaults() + if len(blc.hooks) == 0 { + if err = blc.check(); err != nil { + return nil, err + } + node, err = blc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*BlobLinkMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = blc.check(); err != nil { + return nil, err + } + blc.mutation = mutation + if node, err = blc.sqlSave(ctx); err != nil { + return nil, err + } + return node, err + }) + for i := len(blc.hooks) - 1; i >= 0; i-- { + if blc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = blc.hooks[i](mut) + } + v, err := mut.Mutate(ctx, blc.mutation) + if err != nil { + return nil, err + } + nv, ok := v.(*BlobLink) + if !ok { + return nil, fmt.Errorf("unexpected node type %T returned from BlobLinkMutation", v) + } + node = nv + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (blc *BlobLinkCreate) SaveX(ctx context.Context) *BlobLink { + v, err := blc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (blc *BlobLinkCreate) Exec(ctx context.Context) error { + _, err := blc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (blc *BlobLinkCreate) ExecX(ctx context.Context) { + if err := blc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (blc *BlobLinkCreate) defaults() { + if _, ok := blc.mutation.CreatedAt(); !ok { + v := bloblink.DefaultCreatedAt() + blc.mutation.SetCreatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (blc *BlobLinkCreate) check() error { + if _, ok := blc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "BlobLink.created_at"`)} + } + if _, ok := blc.mutation.BlobID(); !ok { + return &ValidationError{Name: "blob_id", err: errors.New(`ent: missing required field "BlobLink.blob_id"`)} + } + if _, ok := blc.mutation.LinkID(); !ok { + return &ValidationError{Name: "link_id", err: errors.New(`ent: missing required field "BlobLink.link_id"`)} + } + if _, ok := blc.mutation.BlobID(); !ok { + return &ValidationError{Name: "blob", err: errors.New(`ent: missing required edge "BlobLink.blob"`)} + } + if _, ok := blc.mutation.LinkID(); !ok { + return &ValidationError{Name: "link", err: errors.New(`ent: missing required edge "BlobLink.link"`)} + } + return nil +} + +func (blc *BlobLinkCreate) sqlSave(ctx context.Context) (*BlobLink, error) { + _node, _spec := blc.createSpec() + if err := sqlgraph.CreateNode(ctx, blc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + return _node, nil +} + +func (blc *BlobLinkCreate) createSpec() (*BlobLink, *sqlgraph.CreateSpec) { + var ( + _node = &BlobLink{config: blc.config} + _spec = &sqlgraph.CreateSpec{ + Table: bloblink.Table, + } + ) + _spec.OnConflict = blc.conflict + if value, ok := blc.mutation.CreatedAt(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: bloblink.FieldCreatedAt, + }) + _node.CreatedAt = value + } + if nodes := blc.mutation.BlobIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.BlobTable, + Columns: []string{bloblink.BlobColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.BlobID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := blc.mutation.LinkIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.LinkTable, + Columns: []string{bloblink.LinkColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.LinkID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.BlobLink.Create(). +// SetCreatedAt(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.BlobLinkUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +// +func (blc *BlobLinkCreate) OnConflict(opts ...sql.ConflictOption) *BlobLinkUpsertOne { + blc.conflict = opts + return &BlobLinkUpsertOne{ + create: blc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.BlobLink.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +// +func (blc *BlobLinkCreate) OnConflictColumns(columns ...string) *BlobLinkUpsertOne { + blc.conflict = append(blc.conflict, sql.ConflictColumns(columns...)) + return &BlobLinkUpsertOne{ + create: blc, + } +} + +type ( + // BlobLinkUpsertOne is the builder for "upsert"-ing + // one BlobLink node. + BlobLinkUpsertOne struct { + create *BlobLinkCreate + } + + // BlobLinkUpsert is the "OnConflict" setter. + BlobLinkUpsert struct { + *sql.UpdateSet + } +) + +// SetCreatedAt sets the "created_at" field. +func (u *BlobLinkUpsert) SetCreatedAt(v time.Time) *BlobLinkUpsert { + u.Set(bloblink.FieldCreatedAt, v) + return u +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *BlobLinkUpsert) UpdateCreatedAt() *BlobLinkUpsert { + u.SetExcluded(bloblink.FieldCreatedAt) + return u +} + +// SetBlobID sets the "blob_id" field. +func (u *BlobLinkUpsert) SetBlobID(v uuid.UUID) *BlobLinkUpsert { + u.Set(bloblink.FieldBlobID, v) + return u +} + +// UpdateBlobID sets the "blob_id" field to the value that was provided on create. +func (u *BlobLinkUpsert) UpdateBlobID() *BlobLinkUpsert { + u.SetExcluded(bloblink.FieldBlobID) + return u +} + +// SetLinkID sets the "link_id" field. +func (u *BlobLinkUpsert) SetLinkID(v uuid.UUID) *BlobLinkUpsert { + u.Set(bloblink.FieldLinkID, v) + return u +} + +// UpdateLinkID sets the "link_id" field to the value that was provided on create. +func (u *BlobLinkUpsert) UpdateLinkID() *BlobLinkUpsert { + u.SetExcluded(bloblink.FieldLinkID) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.BlobLink.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +// +func (u *BlobLinkUpsertOne) UpdateNewValues() *BlobLinkUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.BlobLink.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +// +func (u *BlobLinkUpsertOne) Ignore() *BlobLinkUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *BlobLinkUpsertOne) DoNothing() *BlobLinkUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the BlobLinkCreate.OnConflict +// documentation for more info. +func (u *BlobLinkUpsertOne) Update(set func(*BlobLinkUpsert)) *BlobLinkUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&BlobLinkUpsert{UpdateSet: update}) + })) + return u +} + +// SetCreatedAt sets the "created_at" field. +func (u *BlobLinkUpsertOne) SetCreatedAt(v time.Time) *BlobLinkUpsertOne { + return u.Update(func(s *BlobLinkUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *BlobLinkUpsertOne) UpdateCreatedAt() *BlobLinkUpsertOne { + return u.Update(func(s *BlobLinkUpsert) { + s.UpdateCreatedAt() + }) +} + +// SetBlobID sets the "blob_id" field. +func (u *BlobLinkUpsertOne) SetBlobID(v uuid.UUID) *BlobLinkUpsertOne { + return u.Update(func(s *BlobLinkUpsert) { + s.SetBlobID(v) + }) +} + +// UpdateBlobID sets the "blob_id" field to the value that was provided on create. +func (u *BlobLinkUpsertOne) UpdateBlobID() *BlobLinkUpsertOne { + return u.Update(func(s *BlobLinkUpsert) { + s.UpdateBlobID() + }) +} + +// SetLinkID sets the "link_id" field. +func (u *BlobLinkUpsertOne) SetLinkID(v uuid.UUID) *BlobLinkUpsertOne { + return u.Update(func(s *BlobLinkUpsert) { + s.SetLinkID(v) + }) +} + +// UpdateLinkID sets the "link_id" field to the value that was provided on create. +func (u *BlobLinkUpsertOne) UpdateLinkID() *BlobLinkUpsertOne { + return u.Update(func(s *BlobLinkUpsert) { + s.UpdateLinkID() + }) +} + +// Exec executes the query. +func (u *BlobLinkUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for BlobLinkCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *BlobLinkUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// BlobLinkCreateBulk is the builder for creating many BlobLink entities in bulk. +type BlobLinkCreateBulk struct { + config + builders []*BlobLinkCreate + conflict []sql.ConflictOption +} + +// Save creates the BlobLink entities in the database. +func (blcb *BlobLinkCreateBulk) Save(ctx context.Context) ([]*BlobLink, error) { + specs := make([]*sqlgraph.CreateSpec, len(blcb.builders)) + nodes := make([]*BlobLink, len(blcb.builders)) + mutators := make([]Mutator, len(blcb.builders)) + for i := range blcb.builders { + func(i int, root context.Context) { + builder := blcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*BlobLinkMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, blcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = blcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, blcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, blcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (blcb *BlobLinkCreateBulk) SaveX(ctx context.Context) []*BlobLink { + v, err := blcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (blcb *BlobLinkCreateBulk) Exec(ctx context.Context) error { + _, err := blcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (blcb *BlobLinkCreateBulk) ExecX(ctx context.Context) { + if err := blcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.BlobLink.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.BlobLinkUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +// +func (blcb *BlobLinkCreateBulk) OnConflict(opts ...sql.ConflictOption) *BlobLinkUpsertBulk { + blcb.conflict = opts + return &BlobLinkUpsertBulk{ + create: blcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.BlobLink.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +// +func (blcb *BlobLinkCreateBulk) OnConflictColumns(columns ...string) *BlobLinkUpsertBulk { + blcb.conflict = append(blcb.conflict, sql.ConflictColumns(columns...)) + return &BlobLinkUpsertBulk{ + create: blcb, + } +} + +// BlobLinkUpsertBulk is the builder for "upsert"-ing +// a bulk of BlobLink nodes. +type BlobLinkUpsertBulk struct { + create *BlobLinkCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.BlobLink.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +// +func (u *BlobLinkUpsertBulk) UpdateNewValues() *BlobLinkUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.BlobLink.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +// +func (u *BlobLinkUpsertBulk) Ignore() *BlobLinkUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *BlobLinkUpsertBulk) DoNothing() *BlobLinkUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the BlobLinkCreateBulk.OnConflict +// documentation for more info. +func (u *BlobLinkUpsertBulk) Update(set func(*BlobLinkUpsert)) *BlobLinkUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&BlobLinkUpsert{UpdateSet: update}) + })) + return u +} + +// SetCreatedAt sets the "created_at" field. +func (u *BlobLinkUpsertBulk) SetCreatedAt(v time.Time) *BlobLinkUpsertBulk { + return u.Update(func(s *BlobLinkUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *BlobLinkUpsertBulk) UpdateCreatedAt() *BlobLinkUpsertBulk { + return u.Update(func(s *BlobLinkUpsert) { + s.UpdateCreatedAt() + }) +} + +// SetBlobID sets the "blob_id" field. +func (u *BlobLinkUpsertBulk) SetBlobID(v uuid.UUID) *BlobLinkUpsertBulk { + return u.Update(func(s *BlobLinkUpsert) { + s.SetBlobID(v) + }) +} + +// UpdateBlobID sets the "blob_id" field to the value that was provided on create. +func (u *BlobLinkUpsertBulk) UpdateBlobID() *BlobLinkUpsertBulk { + return u.Update(func(s *BlobLinkUpsert) { + s.UpdateBlobID() + }) +} + +// SetLinkID sets the "link_id" field. +func (u *BlobLinkUpsertBulk) SetLinkID(v uuid.UUID) *BlobLinkUpsertBulk { + return u.Update(func(s *BlobLinkUpsert) { + s.SetLinkID(v) + }) +} + +// UpdateLinkID sets the "link_id" field to the value that was provided on create. +func (u *BlobLinkUpsertBulk) UpdateLinkID() *BlobLinkUpsertBulk { + return u.Update(func(s *BlobLinkUpsert) { + s.UpdateLinkID() + }) +} + +// Exec executes the query. +func (u *BlobLinkUpsertBulk) Exec(ctx context.Context) error { + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the BlobLinkCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for BlobLinkCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *BlobLinkUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/entc/integration/customid/ent/bloblink_delete.go b/entc/integration/customid/ent/bloblink_delete.go new file mode 100644 index 000000000..1802e088f --- /dev/null +++ b/entc/integration/customid/ent/bloblink_delete.go @@ -0,0 +1,114 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/entc/integration/customid/ent/bloblink" + "entgo.io/ent/entc/integration/customid/ent/predicate" +) + +// BlobLinkDelete is the builder for deleting a BlobLink entity. +type BlobLinkDelete struct { + config + hooks []Hook + mutation *BlobLinkMutation +} + +// Where appends a list predicates to the BlobLinkDelete builder. +func (bld *BlobLinkDelete) Where(ps ...predicate.BlobLink) *BlobLinkDelete { + bld.mutation.Where(ps...) + return bld +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (bld *BlobLinkDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(bld.hooks) == 0 { + affected, err = bld.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*BlobLinkMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + bld.mutation = mutation + affected, err = bld.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(bld.hooks) - 1; i >= 0; i-- { + if bld.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = bld.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, bld.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (bld *BlobLinkDelete) ExecX(ctx context.Context) int { + n, err := bld.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (bld *BlobLinkDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: bloblink.Table, + }, + } + if ps := bld.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, bld.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return affected, err +} + +// BlobLinkDeleteOne is the builder for deleting a single BlobLink entity. +type BlobLinkDeleteOne struct { + bld *BlobLinkDelete +} + +// Exec executes the deletion query. +func (bldo *BlobLinkDeleteOne) Exec(ctx context.Context) error { + n, err := bldo.bld.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{bloblink.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (bldo *BlobLinkDeleteOne) ExecX(ctx context.Context) { + bldo.bld.ExecX(ctx) +} diff --git a/entc/integration/customid/ent/bloblink_query.go b/entc/integration/customid/ent/bloblink_query.go new file mode 100644 index 000000000..ba8ad9ad5 --- /dev/null +++ b/entc/integration/customid/ent/bloblink_query.go @@ -0,0 +1,584 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" + "entgo.io/ent/entc/integration/customid/ent/predicate" + "github.com/google/uuid" +) + +// BlobLinkQuery is the builder for querying BlobLink entities. +type BlobLinkQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.BlobLink + // eager-loading edges. + withBlob *BlobQuery + withLink *BlobQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the BlobLinkQuery builder. +func (blq *BlobLinkQuery) Where(ps ...predicate.BlobLink) *BlobLinkQuery { + blq.predicates = append(blq.predicates, ps...) + return blq +} + +// Limit adds a limit step to the query. +func (blq *BlobLinkQuery) Limit(limit int) *BlobLinkQuery { + blq.limit = &limit + return blq +} + +// Offset adds an offset step to the query. +func (blq *BlobLinkQuery) Offset(offset int) *BlobLinkQuery { + blq.offset = &offset + return blq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (blq *BlobLinkQuery) Unique(unique bool) *BlobLinkQuery { + blq.unique = &unique + return blq +} + +// Order adds an order step to the query. +func (blq *BlobLinkQuery) Order(o ...OrderFunc) *BlobLinkQuery { + blq.order = append(blq.order, o...) + return blq +} + +// QueryBlob chains the current query on the "blob" edge. +func (blq *BlobLinkQuery) QueryBlob() *BlobQuery { + query := &BlobQuery{config: blq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := blq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := blq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(bloblink.Table, bloblink.BlobColumn, selector), + sqlgraph.To(blob.Table, blob.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, bloblink.BlobTable, bloblink.BlobColumn), + ) + fromU = sqlgraph.SetNeighbors(blq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryLink chains the current query on the "link" edge. +func (blq *BlobLinkQuery) QueryLink() *BlobQuery { + query := &BlobQuery{config: blq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := blq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := blq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(bloblink.Table, bloblink.LinkColumn, selector), + sqlgraph.To(blob.Table, blob.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, bloblink.LinkTable, bloblink.LinkColumn), + ) + fromU = sqlgraph.SetNeighbors(blq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first BlobLink entity from the query. +// Returns a *NotFoundError when no BlobLink was found. +func (blq *BlobLinkQuery) First(ctx context.Context) (*BlobLink, error) { + nodes, err := blq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{bloblink.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (blq *BlobLinkQuery) FirstX(ctx context.Context) *BlobLink { + node, err := blq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// Only returns a single BlobLink entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one BlobLink entity is found. +// Returns a *NotFoundError when no BlobLink entities are found. +func (blq *BlobLinkQuery) Only(ctx context.Context) (*BlobLink, error) { + nodes, err := blq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{bloblink.Label} + default: + return nil, &NotSingularError{bloblink.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (blq *BlobLinkQuery) OnlyX(ctx context.Context) *BlobLink { + node, err := blq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// All executes the query and returns a list of BlobLinks. +func (blq *BlobLinkQuery) All(ctx context.Context) ([]*BlobLink, error) { + if err := blq.prepareQuery(ctx); err != nil { + return nil, err + } + return blq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (blq *BlobLinkQuery) AllX(ctx context.Context) []*BlobLink { + nodes, err := blq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// Count returns the count of the given query. +func (blq *BlobLinkQuery) Count(ctx context.Context) (int, error) { + if err := blq.prepareQuery(ctx); err != nil { + return 0, err + } + return blq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (blq *BlobLinkQuery) CountX(ctx context.Context) int { + count, err := blq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (blq *BlobLinkQuery) Exist(ctx context.Context) (bool, error) { + if err := blq.prepareQuery(ctx); err != nil { + return false, err + } + return blq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (blq *BlobLinkQuery) ExistX(ctx context.Context) bool { + exist, err := blq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the BlobLinkQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (blq *BlobLinkQuery) Clone() *BlobLinkQuery { + if blq == nil { + return nil + } + return &BlobLinkQuery{ + config: blq.config, + limit: blq.limit, + offset: blq.offset, + order: append([]OrderFunc{}, blq.order...), + predicates: append([]predicate.BlobLink{}, blq.predicates...), + withBlob: blq.withBlob.Clone(), + withLink: blq.withLink.Clone(), + // clone intermediate query. + sql: blq.sql.Clone(), + path: blq.path, + unique: blq.unique, + } +} + +// WithBlob tells the query-builder to eager-load the nodes that are connected to +// the "blob" edge. The optional arguments are used to configure the query builder of the edge. +func (blq *BlobLinkQuery) WithBlob(opts ...func(*BlobQuery)) *BlobLinkQuery { + query := &BlobQuery{config: blq.config} + for _, opt := range opts { + opt(query) + } + blq.withBlob = query + return blq +} + +// WithLink tells the query-builder to eager-load the nodes that are connected to +// the "link" edge. The optional arguments are used to configure the query builder of the edge. +func (blq *BlobLinkQuery) WithLink(opts ...func(*BlobQuery)) *BlobLinkQuery { + query := &BlobQuery{config: blq.config} + for _, opt := range opts { + opt(query) + } + blq.withLink = query + return blq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.BlobLink.Query(). +// GroupBy(bloblink.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (blq *BlobLinkQuery) GroupBy(field string, fields ...string) *BlobLinkGroupBy { + grbuild := &BlobLinkGroupBy{config: blq.config} + grbuild.fields = append([]string{field}, fields...) + grbuild.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := blq.prepareQuery(ctx); err != nil { + return nil, err + } + return blq.sqlQuery(ctx), nil + } + grbuild.label = bloblink.Label + grbuild.flds, grbuild.scan = &grbuild.fields, grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.BlobLink.Query(). +// Select(bloblink.FieldCreatedAt). +// Scan(ctx, &v) +// +func (blq *BlobLinkQuery) Select(fields ...string) *BlobLinkSelect { + blq.fields = append(blq.fields, fields...) + selbuild := &BlobLinkSelect{BlobLinkQuery: blq} + selbuild.label = bloblink.Label + selbuild.flds, selbuild.scan = &blq.fields, selbuild.Scan + return selbuild +} + +func (blq *BlobLinkQuery) prepareQuery(ctx context.Context) error { + for _, f := range blq.fields { + if !bloblink.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if blq.path != nil { + prev, err := blq.path(ctx) + if err != nil { + return err + } + blq.sql = prev + } + return nil +} + +func (blq *BlobLinkQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*BlobLink, error) { + var ( + nodes = []*BlobLink{} + _spec = blq.querySpec() + loadedTypes = [2]bool{ + blq.withBlob != nil, + blq.withLink != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + return (*BlobLink).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + node := &BlobLink{config: blq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, blq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := blq.withBlob; query != nil { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*BlobLink) + for i := range nodes { + fk := nodes[i].BlobID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(blob.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "blob_id" returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.Blob = n + } + } + } + + if query := blq.withLink; query != nil { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*BlobLink) + for i := range nodes { + fk := nodes[i].LinkID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(blob.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "link_id" returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.Link = n + } + } + } + + return nodes, nil +} + +func (blq *BlobLinkQuery) sqlCount(ctx context.Context) (int, error) { + _spec := blq.querySpec() + _spec.Unique = false + _spec.Node.Columns = nil + return sqlgraph.CountNodes(ctx, blq.driver, _spec) +} + +func (blq *BlobLinkQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := blq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (blq *BlobLinkQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: bloblink.Table, + Columns: bloblink.Columns, + }, + From: blq.sql, + Unique: true, + } + if unique := blq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := blq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + for i := range fields { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if ps := blq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := blq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := blq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := blq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (blq *BlobLinkQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(blq.driver.Dialect()) + t1 := builder.Table(bloblink.Table) + columns := blq.fields + if len(columns) == 0 { + columns = bloblink.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if blq.sql != nil { + selector = blq.sql + selector.Select(selector.Columns(columns...)...) + } + if blq.unique != nil && *blq.unique { + selector.Distinct() + } + for _, p := range blq.predicates { + p(selector) + } + for _, p := range blq.order { + p(selector) + } + if offset := blq.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 := blq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// BlobLinkGroupBy is the group-by builder for BlobLink entities. +type BlobLinkGroupBy struct { + config + selector + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (blgb *BlobLinkGroupBy) Aggregate(fns ...AggregateFunc) *BlobLinkGroupBy { + blgb.fns = append(blgb.fns, fns...) + return blgb +} + +// Scan applies the group-by query and scans the result into the given value. +func (blgb *BlobLinkGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := blgb.path(ctx) + if err != nil { + return err + } + blgb.sql = query + return blgb.sqlScan(ctx, v) +} + +func (blgb *BlobLinkGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range blgb.fields { + if !bloblink.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := blgb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := blgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (blgb *BlobLinkGroupBy) sqlQuery() *sql.Selector { + selector := blgb.sql.Select() + aggregation := make([]string, 0, len(blgb.fns)) + for _, fn := range blgb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(blgb.fields)+len(blgb.fns)) + for _, f := range blgb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(blgb.fields...)...) +} + +// BlobLinkSelect is the builder for selecting fields of BlobLink entities. +type BlobLinkSelect struct { + *BlobLinkQuery + selector + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (bls *BlobLinkSelect) Scan(ctx context.Context, v interface{}) error { + if err := bls.prepareQuery(ctx); err != nil { + return err + } + bls.sql = bls.BlobLinkQuery.sqlQuery(ctx) + return bls.sqlScan(ctx, v) +} + +func (bls *BlobLinkSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := bls.sql.Query() + if err := bls.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/entc/integration/customid/ent/bloblink_update.go b/entc/integration/customid/ent/bloblink_update.go new file mode 100644 index 000000000..a185970e1 --- /dev/null +++ b/entc/integration/customid/ent/bloblink_update.go @@ -0,0 +1,550 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" + "entgo.io/ent/entc/integration/customid/ent/predicate" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// BlobLinkUpdate is the builder for updating BlobLink entities. +type BlobLinkUpdate struct { + config + hooks []Hook + mutation *BlobLinkMutation +} + +// Where appends a list predicates to the BlobLinkUpdate builder. +func (blu *BlobLinkUpdate) Where(ps ...predicate.BlobLink) *BlobLinkUpdate { + blu.mutation.Where(ps...) + return blu +} + +// SetCreatedAt sets the "created_at" field. +func (blu *BlobLinkUpdate) SetCreatedAt(t time.Time) *BlobLinkUpdate { + blu.mutation.SetCreatedAt(t) + return blu +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (blu *BlobLinkUpdate) SetNillableCreatedAt(t *time.Time) *BlobLinkUpdate { + if t != nil { + blu.SetCreatedAt(*t) + } + return blu +} + +// SetBlobID sets the "blob_id" field. +func (blu *BlobLinkUpdate) SetBlobID(u uuid.UUID) *BlobLinkUpdate { + blu.mutation.SetBlobID(u) + return blu +} + +// SetLinkID sets the "link_id" field. +func (blu *BlobLinkUpdate) SetLinkID(u uuid.UUID) *BlobLinkUpdate { + blu.mutation.SetLinkID(u) + return blu +} + +// SetBlob sets the "blob" edge to the Blob entity. +func (blu *BlobLinkUpdate) SetBlob(b *Blob) *BlobLinkUpdate { + return blu.SetBlobID(b.ID) +} + +// SetLink sets the "link" edge to the Blob entity. +func (blu *BlobLinkUpdate) SetLink(b *Blob) *BlobLinkUpdate { + return blu.SetLinkID(b.ID) +} + +// Mutation returns the BlobLinkMutation object of the builder. +func (blu *BlobLinkUpdate) Mutation() *BlobLinkMutation { + return blu.mutation +} + +// ClearBlob clears the "blob" edge to the Blob entity. +func (blu *BlobLinkUpdate) ClearBlob() *BlobLinkUpdate { + blu.mutation.ClearBlob() + return blu +} + +// ClearLink clears the "link" edge to the Blob entity. +func (blu *BlobLinkUpdate) ClearLink() *BlobLinkUpdate { + blu.mutation.ClearLink() + return blu +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (blu *BlobLinkUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(blu.hooks) == 0 { + if err = blu.check(); err != nil { + return 0, err + } + affected, err = blu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*BlobLinkMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = blu.check(); err != nil { + return 0, err + } + blu.mutation = mutation + affected, err = blu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(blu.hooks) - 1; i >= 0; i-- { + if blu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = blu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, blu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (blu *BlobLinkUpdate) SaveX(ctx context.Context) int { + affected, err := blu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (blu *BlobLinkUpdate) Exec(ctx context.Context) error { + _, err := blu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (blu *BlobLinkUpdate) ExecX(ctx context.Context) { + if err := blu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (blu *BlobLinkUpdate) check() error { + if _, ok := blu.mutation.BlobID(); blu.mutation.BlobCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "BlobLink.blob"`) + } + if _, ok := blu.mutation.LinkID(); blu.mutation.LinkCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "BlobLink.link"`) + } + return nil +} + +func (blu *BlobLinkUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: bloblink.Table, + Columns: bloblink.Columns, + CompositeID: []*sqlgraph.FieldSpec{ + { + Type: field.TypeUUID, + Column: bloblink.FieldBlobID, + }, + { + Type: field.TypeUUID, + Column: bloblink.FieldLinkID, + }, + }, + }, + } + if ps := blu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := blu.mutation.CreatedAt(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: bloblink.FieldCreatedAt, + }) + } + if blu.mutation.BlobCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.BlobTable, + Columns: []string{bloblink.BlobColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := blu.mutation.BlobIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.BlobTable, + Columns: []string{bloblink.BlobColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if blu.mutation.LinkCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.LinkTable, + Columns: []string{bloblink.LinkColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := blu.mutation.LinkIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.LinkTable, + Columns: []string{bloblink.LinkColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.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, blu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{bloblink.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + return n, nil +} + +// BlobLinkUpdateOne is the builder for updating a single BlobLink entity. +type BlobLinkUpdateOne struct { + config + fields []string + hooks []Hook + mutation *BlobLinkMutation +} + +// SetCreatedAt sets the "created_at" field. +func (bluo *BlobLinkUpdateOne) SetCreatedAt(t time.Time) *BlobLinkUpdateOne { + bluo.mutation.SetCreatedAt(t) + return bluo +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (bluo *BlobLinkUpdateOne) SetNillableCreatedAt(t *time.Time) *BlobLinkUpdateOne { + if t != nil { + bluo.SetCreatedAt(*t) + } + return bluo +} + +// SetBlobID sets the "blob_id" field. +func (bluo *BlobLinkUpdateOne) SetBlobID(u uuid.UUID) *BlobLinkUpdateOne { + bluo.mutation.SetBlobID(u) + return bluo +} + +// SetLinkID sets the "link_id" field. +func (bluo *BlobLinkUpdateOne) SetLinkID(u uuid.UUID) *BlobLinkUpdateOne { + bluo.mutation.SetLinkID(u) + return bluo +} + +// SetBlob sets the "blob" edge to the Blob entity. +func (bluo *BlobLinkUpdateOne) SetBlob(b *Blob) *BlobLinkUpdateOne { + return bluo.SetBlobID(b.ID) +} + +// SetLink sets the "link" edge to the Blob entity. +func (bluo *BlobLinkUpdateOne) SetLink(b *Blob) *BlobLinkUpdateOne { + return bluo.SetLinkID(b.ID) +} + +// Mutation returns the BlobLinkMutation object of the builder. +func (bluo *BlobLinkUpdateOne) Mutation() *BlobLinkMutation { + return bluo.mutation +} + +// ClearBlob clears the "blob" edge to the Blob entity. +func (bluo *BlobLinkUpdateOne) ClearBlob() *BlobLinkUpdateOne { + bluo.mutation.ClearBlob() + return bluo +} + +// ClearLink clears the "link" edge to the Blob entity. +func (bluo *BlobLinkUpdateOne) ClearLink() *BlobLinkUpdateOne { + bluo.mutation.ClearLink() + return bluo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (bluo *BlobLinkUpdateOne) Select(field string, fields ...string) *BlobLinkUpdateOne { + bluo.fields = append([]string{field}, fields...) + return bluo +} + +// Save executes the query and returns the updated BlobLink entity. +func (bluo *BlobLinkUpdateOne) Save(ctx context.Context) (*BlobLink, error) { + var ( + err error + node *BlobLink + ) + if len(bluo.hooks) == 0 { + if err = bluo.check(); err != nil { + return nil, err + } + node, err = bluo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*BlobLinkMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = bluo.check(); err != nil { + return nil, err + } + bluo.mutation = mutation + node, err = bluo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(bluo.hooks) - 1; i >= 0; i-- { + if bluo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = bluo.hooks[i](mut) + } + v, err := mut.Mutate(ctx, bluo.mutation) + if err != nil { + return nil, err + } + nv, ok := v.(*BlobLink) + if !ok { + return nil, fmt.Errorf("unexpected node type %T returned from BlobLinkMutation", v) + } + node = nv + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (bluo *BlobLinkUpdateOne) SaveX(ctx context.Context) *BlobLink { + node, err := bluo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (bluo *BlobLinkUpdateOne) Exec(ctx context.Context) error { + _, err := bluo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (bluo *BlobLinkUpdateOne) ExecX(ctx context.Context) { + if err := bluo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (bluo *BlobLinkUpdateOne) check() error { + if _, ok := bluo.mutation.BlobID(); bluo.mutation.BlobCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "BlobLink.blob"`) + } + if _, ok := bluo.mutation.LinkID(); bluo.mutation.LinkCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "BlobLink.link"`) + } + return nil +} + +func (bluo *BlobLinkUpdateOne) sqlSave(ctx context.Context) (_node *BlobLink, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: bloblink.Table, + Columns: bloblink.Columns, + CompositeID: []*sqlgraph.FieldSpec{ + { + Type: field.TypeUUID, + Column: bloblink.FieldBlobID, + }, + { + Type: field.TypeUUID, + Column: bloblink.FieldLinkID, + }, + }, + }, + } + if id, ok := bluo.mutation.BlobID(); !ok { + return nil, &ValidationError{Name: "blob_id", err: errors.New(`ent: missing "BlobLink.blob_id" for update`)} + } else { + _spec.Node.CompositeID[0].Value = id + } + if id, ok := bluo.mutation.LinkID(); !ok { + return nil, &ValidationError{Name: "link_id", err: errors.New(`ent: missing "BlobLink.link_id" for update`)} + } else { + _spec.Node.CompositeID[1].Value = id + } + if fields := bluo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, len(fields)) + for i, f := range fields { + if !bloblink.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + _spec.Node.Columns[i] = f + } + } + if ps := bluo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := bluo.mutation.CreatedAt(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: bloblink.FieldCreatedAt, + }) + } + if bluo.mutation.BlobCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.BlobTable, + Columns: []string{bloblink.BlobColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := bluo.mutation.BlobIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.BlobTable, + Columns: []string{bloblink.BlobColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if bluo.mutation.LinkCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.LinkTable, + Columns: []string{bloblink.LinkColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := bluo.mutation.LinkIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.LinkTable, + Columns: []string{bloblink.LinkColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: blob.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &BlobLink{config: bluo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, bluo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{bloblink.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + return _node, nil +} diff --git a/entc/integration/customid/ent/client.go b/entc/integration/customid/ent/client.go index 497c75146..e0ec3d42a 100644 --- a/entc/integration/customid/ent/client.go +++ b/entc/integration/customid/ent/client.go @@ -18,6 +18,7 @@ import ( "entgo.io/ent/entc/integration/customid/ent/account" "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" "entgo.io/ent/entc/integration/customid/ent/car" "entgo.io/ent/entc/integration/customid/ent/device" "entgo.io/ent/entc/integration/customid/ent/doc" @@ -46,6 +47,8 @@ type Client struct { Account *AccountClient // Blob is the client for interacting with the Blob builders. Blob *BlobClient + // BlobLink is the client for interacting with the BlobLink builders. + BlobLink *BlobLinkClient // Car is the client for interacting with the Car builders. Car *CarClient // Device is the client for interacting with the Device builders. @@ -87,6 +90,7 @@ func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) c.Account = NewAccountClient(c.config) c.Blob = NewBlobClient(c.config) + c.BlobLink = NewBlobLinkClient(c.config) c.Car = NewCarClient(c.config) c.Device = NewDeviceClient(c.config) c.Doc = NewDocClient(c.config) @@ -135,6 +139,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { config: cfg, Account: NewAccountClient(cfg), Blob: NewBlobClient(cfg), + BlobLink: NewBlobLinkClient(cfg), Car: NewCarClient(cfg), Device: NewDeviceClient(cfg), Doc: NewDocClient(cfg), @@ -169,6 +174,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) config: cfg, Account: NewAccountClient(cfg), Blob: NewBlobClient(cfg), + BlobLink: NewBlobLinkClient(cfg), Car: NewCarClient(cfg), Device: NewDeviceClient(cfg), Doc: NewDocClient(cfg), @@ -213,6 +219,7 @@ func (c *Client) Close() error { func (c *Client) Use(hooks ...Hook) { c.Account.Use(hooks...) c.Blob.Use(hooks...) + c.BlobLink.Use(hooks...) c.Car.Use(hooks...) c.Device.Use(hooks...) c.Doc.Use(hooks...) @@ -451,11 +458,100 @@ func (c *BlobClient) QueryLinks(b *Blob) *BlobQuery { return query } +// QueryBlobLinks queries the blob_links edge of a Blob. +func (c *BlobClient) QueryBlobLinks(b *Blob) *BlobLinkQuery { + query := &BlobLinkQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := b.ID + step := sqlgraph.NewStep( + sqlgraph.From(blob.Table, blob.FieldID, id), + sqlgraph.To(bloblink.Table, bloblink.BlobColumn), + sqlgraph.Edge(sqlgraph.O2M, true, blob.BlobLinksTable, blob.BlobLinksColumn), + ) + fromV = sqlgraph.Neighbors(b.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *BlobClient) Hooks() []Hook { return c.hooks.Blob } +// BlobLinkClient is a client for the BlobLink schema. +type BlobLinkClient struct { + config +} + +// NewBlobLinkClient returns a client for the BlobLink from the given config. +func NewBlobLinkClient(c config) *BlobLinkClient { + return &BlobLinkClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `bloblink.Hooks(f(g(h())))`. +func (c *BlobLinkClient) Use(hooks ...Hook) { + c.hooks.BlobLink = append(c.hooks.BlobLink, hooks...) +} + +// Create returns a builder for creating a BlobLink entity. +func (c *BlobLinkClient) Create() *BlobLinkCreate { + mutation := newBlobLinkMutation(c.config, OpCreate) + return &BlobLinkCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of BlobLink entities. +func (c *BlobLinkClient) CreateBulk(builders ...*BlobLinkCreate) *BlobLinkCreateBulk { + return &BlobLinkCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for BlobLink. +func (c *BlobLinkClient) Update() *BlobLinkUpdate { + mutation := newBlobLinkMutation(c.config, OpUpdate) + return &BlobLinkUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *BlobLinkClient) UpdateOne(bl *BlobLink) *BlobLinkUpdateOne { + mutation := newBlobLinkMutation(c.config, OpUpdateOne) + mutation.blob = &bl.BlobID + mutation.link = &bl.LinkID + return &BlobLinkUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for BlobLink. +func (c *BlobLinkClient) Delete() *BlobLinkDelete { + mutation := newBlobLinkMutation(c.config, OpDelete) + return &BlobLinkDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Query returns a query builder for BlobLink. +func (c *BlobLinkClient) Query() *BlobLinkQuery { + return &BlobLinkQuery{ + config: c.config, + } +} + +// QueryBlob queries the blob edge of a BlobLink. +func (c *BlobLinkClient) QueryBlob(bl *BlobLink) *BlobQuery { + return c.Query(). + Where(bloblink.BlobID(bl.BlobID), bloblink.LinkID(bl.LinkID)). + QueryBlob() +} + +// QueryLink queries the link edge of a BlobLink. +func (c *BlobLinkClient) QueryLink(bl *BlobLink) *BlobQuery { + return c.Query(). + Where(bloblink.BlobID(bl.BlobID), bloblink.LinkID(bl.LinkID)). + QueryLink() +} + +// Hooks returns the client hooks. +func (c *BlobLinkClient) Hooks() []Hook { + return c.hooks.BlobLink +} + // CarClient is a client for the Car schema. type CarClient struct { config diff --git a/entc/integration/customid/ent/config.go b/entc/integration/customid/ent/config.go index d4d4f2521..94dfc7f2c 100644 --- a/entc/integration/customid/ent/config.go +++ b/entc/integration/customid/ent/config.go @@ -30,6 +30,7 @@ type config struct { type hooks struct { Account []ent.Hook Blob []ent.Hook + BlobLink []ent.Hook Car []ent.Hook Device []ent.Hook Doc []ent.Hook diff --git a/entc/integration/customid/ent/ent.go b/entc/integration/customid/ent/ent.go index 4f5bae55a..b06523ab1 100644 --- a/entc/integration/customid/ent/ent.go +++ b/entc/integration/customid/ent/ent.go @@ -16,6 +16,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/entc/integration/customid/ent/account" "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" "entgo.io/ent/entc/integration/customid/ent/car" "entgo.io/ent/entc/integration/customid/ent/device" "entgo.io/ent/entc/integration/customid/ent/doc" @@ -51,6 +52,7 @@ func columnChecker(table string) func(string) error { checks := map[string]func(string) bool{ account.Table: account.ValidColumn, blob.Table: blob.ValidColumn, + bloblink.Table: bloblink.ValidColumn, car.Table: car.ValidColumn, device.Table: device.ValidColumn, doc.Table: doc.ValidColumn, diff --git a/entc/integration/customid/ent/entql.go b/entc/integration/customid/ent/entql.go index 32de4ece0..35093f734 100644 --- a/entc/integration/customid/ent/entql.go +++ b/entc/integration/customid/ent/entql.go @@ -9,6 +9,7 @@ package ent import ( "entgo.io/ent/entc/integration/customid/ent/account" "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" "entgo.io/ent/entc/integration/customid/ent/car" "entgo.io/ent/entc/integration/customid/ent/device" "entgo.io/ent/entc/integration/customid/ent/doc" @@ -32,7 +33,7 @@ import ( // schemaGraph holds a representation of ent/schema at runtime. var schemaGraph = func() *sqlgraph.Schema { - graph := &sqlgraph.Schema{Nodes: make([]*sqlgraph.Node, 15)} + graph := &sqlgraph.Schema{Nodes: make([]*sqlgraph.Node, 16)} graph.Nodes[0] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: account.Table, @@ -63,6 +64,18 @@ var schemaGraph = func() *sqlgraph.Schema { }, } graph.Nodes[2] = &sqlgraph.Node{ + NodeSpec: sqlgraph.NodeSpec{ + Table: bloblink.Table, + Columns: bloblink.Columns, + }, + Type: "BlobLink", + Fields: map[string]*sqlgraph.FieldSpec{ + bloblink.FieldCreatedAt: {Type: field.TypeTime, Column: bloblink.FieldCreatedAt}, + bloblink.FieldBlobID: {Type: field.TypeUUID, Column: bloblink.FieldBlobID}, + bloblink.FieldLinkID: {Type: field.TypeUUID, Column: bloblink.FieldLinkID}, + }, + } + graph.Nodes[3] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: car.Table, Columns: car.Columns, @@ -78,7 +91,7 @@ var schemaGraph = func() *sqlgraph.Schema { car.FieldModel: {Type: field.TypeString, Column: car.FieldModel}, }, } - graph.Nodes[3] = &sqlgraph.Node{ + graph.Nodes[4] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: device.Table, Columns: device.Columns, @@ -90,7 +103,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "Device", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[4] = &sqlgraph.Node{ + graph.Nodes[5] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: doc.Table, Columns: doc.Columns, @@ -104,7 +117,7 @@ var schemaGraph = func() *sqlgraph.Schema { doc.FieldText: {Type: field.TypeString, Column: doc.FieldText}, }, } - graph.Nodes[5] = &sqlgraph.Node{ + graph.Nodes[6] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: group.Table, Columns: group.Columns, @@ -116,7 +129,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "Group", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[6] = &sqlgraph.Node{ + graph.Nodes[7] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: intsid.Table, Columns: intsid.Columns, @@ -128,7 +141,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "IntSID", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[7] = &sqlgraph.Node{ + graph.Nodes[8] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: mixinid.Table, Columns: mixinid.Columns, @@ -143,7 +156,7 @@ var schemaGraph = func() *sqlgraph.Schema { mixinid.FieldMixinField: {Type: field.TypeString, Column: mixinid.FieldMixinField}, }, } - graph.Nodes[8] = &sqlgraph.Node{ + graph.Nodes[9] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: note.Table, Columns: note.Columns, @@ -157,7 +170,7 @@ var schemaGraph = func() *sqlgraph.Schema { note.FieldText: {Type: field.TypeString, Column: note.FieldText}, }, } - graph.Nodes[9] = &sqlgraph.Node{ + graph.Nodes[10] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: other.Table, Columns: other.Columns, @@ -169,7 +182,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "Other", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[10] = &sqlgraph.Node{ + graph.Nodes[11] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: pet.Table, Columns: pet.Columns, @@ -181,7 +194,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "Pet", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[11] = &sqlgraph.Node{ + graph.Nodes[12] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: revision.Table, Columns: revision.Columns, @@ -193,7 +206,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "Revision", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[12] = &sqlgraph.Node{ + graph.Nodes[13] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: session.Table, Columns: session.Columns, @@ -205,7 +218,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "Session", Fields: map[string]*sqlgraph.FieldSpec{}, } - graph.Nodes[13] = &sqlgraph.Node{ + graph.Nodes[14] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: token.Table, Columns: token.Columns, @@ -219,7 +232,7 @@ var schemaGraph = func() *sqlgraph.Schema { token.FieldBody: {Type: field.TypeString, Column: token.FieldBody}, }, } - graph.Nodes[14] = &sqlgraph.Node{ + graph.Nodes[15] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: user.Table, Columns: user.Columns, @@ -267,6 +280,42 @@ var schemaGraph = func() *sqlgraph.Schema { "Blob", "Blob", ) + graph.MustAddE( + "blob_links", + &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: blob.BlobLinksTable, + Columns: []string{blob.BlobLinksColumn}, + Bidi: false, + }, + "Blob", + "BlobLink", + ) + graph.MustAddE( + "blob", + &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.BlobTable, + Columns: []string{bloblink.BlobColumn}, + Bidi: false, + }, + "BlobLink", + "Blob", + ) + graph.MustAddE( + "link", + &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: bloblink.LinkTable, + Columns: []string{bloblink.LinkColumn}, + Bidi: false, + }, + "BlobLink", + "Blob", + ) graph.MustAddE( "owner", &sqlgraph.EdgeSpec{ @@ -653,6 +702,98 @@ func (f *BlobFilter) WhereHasLinksWith(preds ...predicate.Blob) { }))) } +// WhereHasBlobLinks applies a predicate to check if query has an edge blob_links. +func (f *BlobFilter) WhereHasBlobLinks() { + f.Where(entql.HasEdge("blob_links")) +} + +// WhereHasBlobLinksWith applies a predicate to check if query has an edge blob_links with a given conditions (other predicates). +func (f *BlobFilter) WhereHasBlobLinksWith(preds ...predicate.BlobLink) { + f.Where(entql.HasEdgeWith("blob_links", sqlgraph.WrapFunc(func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }))) +} + +// addPredicate implements the predicateAdder interface. +func (blq *BlobLinkQuery) addPredicate(pred func(s *sql.Selector)) { + blq.predicates = append(blq.predicates, pred) +} + +// Filter returns a Filter implementation to apply filters on the BlobLinkQuery builder. +func (blq *BlobLinkQuery) Filter() *BlobLinkFilter { + return &BlobLinkFilter{config: blq.config, predicateAdder: blq} +} + +// addPredicate implements the predicateAdder interface. +func (m *BlobLinkMutation) addPredicate(pred func(s *sql.Selector)) { + m.predicates = append(m.predicates, pred) +} + +// Filter returns an entql.Where implementation to apply filters on the BlobLinkMutation builder. +func (m *BlobLinkMutation) Filter() *BlobLinkFilter { + return &BlobLinkFilter{config: m.config, predicateAdder: m} +} + +// BlobLinkFilter provides a generic filtering capability at runtime for BlobLinkQuery. +type BlobLinkFilter struct { + predicateAdder + config +} + +// Where applies the entql predicate on the query filter. +func (f *BlobLinkFilter) Where(p entql.P) { + f.addPredicate(func(s *sql.Selector) { + if err := schemaGraph.EvalP(schemaGraph.Nodes[2].Type, p, s); err != nil { + s.AddError(err) + } + }) +} + +// WhereCreatedAt applies the entql time.Time predicate on the created_at field. +func (f *BlobLinkFilter) WhereCreatedAt(p entql.TimeP) { + f.Where(p.Field(bloblink.FieldCreatedAt)) +} + +// WhereBlobID applies the entql [16]byte predicate on the blob_id field. +func (f *BlobLinkFilter) WhereBlobID(p entql.ValueP) { + f.Where(p.Field(bloblink.FieldBlobID)) +} + +// WhereLinkID applies the entql [16]byte predicate on the link_id field. +func (f *BlobLinkFilter) WhereLinkID(p entql.ValueP) { + f.Where(p.Field(bloblink.FieldLinkID)) +} + +// WhereHasBlob applies a predicate to check if query has an edge blob. +func (f *BlobLinkFilter) WhereHasBlob() { + f.Where(entql.HasEdge("blob")) +} + +// WhereHasBlobWith applies a predicate to check if query has an edge blob with a given conditions (other predicates). +func (f *BlobLinkFilter) WhereHasBlobWith(preds ...predicate.Blob) { + f.Where(entql.HasEdgeWith("blob", sqlgraph.WrapFunc(func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }))) +} + +// WhereHasLink applies a predicate to check if query has an edge link. +func (f *BlobLinkFilter) WhereHasLink() { + f.Where(entql.HasEdge("link")) +} + +// WhereHasLinkWith applies a predicate to check if query has an edge link with a given conditions (other predicates). +func (f *BlobLinkFilter) WhereHasLinkWith(preds ...predicate.Blob) { + f.Where(entql.HasEdgeWith("link", sqlgraph.WrapFunc(func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }))) +} + // addPredicate implements the predicateAdder interface. func (cq *CarQuery) addPredicate(pred func(s *sql.Selector)) { cq.predicates = append(cq.predicates, pred) @@ -682,7 +823,7 @@ type CarFilter struct { // Where applies the entql predicate on the query filter. func (f *CarFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[2].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[3].Type, p, s); err != nil { s.AddError(err) } }) @@ -751,7 +892,7 @@ type DeviceFilter struct { // Where applies the entql predicate on the query filter. func (f *DeviceFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[3].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[4].Type, p, s); err != nil { s.AddError(err) } }) @@ -819,7 +960,7 @@ type DocFilter struct { // Where applies the entql predicate on the query filter. func (f *DocFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[4].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[5].Type, p, s); err != nil { s.AddError(err) } }) @@ -892,7 +1033,7 @@ type GroupFilter struct { // Where applies the entql predicate on the query filter. func (f *GroupFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[5].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[6].Type, p, s); err != nil { s.AddError(err) } }) @@ -946,7 +1087,7 @@ type IntSIDFilter struct { // Where applies the entql predicate on the query filter. func (f *IntSIDFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[6].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[7].Type, p, s); err != nil { s.AddError(err) } }) @@ -1014,7 +1155,7 @@ type MixinIDFilter struct { // Where applies the entql predicate on the query filter. func (f *MixinIDFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[7].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[8].Type, p, s); err != nil { s.AddError(err) } }) @@ -1064,7 +1205,7 @@ type NoteFilter struct { // Where applies the entql predicate on the query filter. func (f *NoteFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[8].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[9].Type, p, s); err != nil { s.AddError(err) } }) @@ -1137,7 +1278,7 @@ type OtherFilter struct { // Where applies the entql predicate on the query filter. func (f *OtherFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[9].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[10].Type, p, s); err != nil { s.AddError(err) } }) @@ -1177,7 +1318,7 @@ type PetFilter struct { // Where applies the entql predicate on the query filter. func (f *PetFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[10].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[11].Type, p, s); err != nil { s.AddError(err) } }) @@ -1273,7 +1414,7 @@ type RevisionFilter struct { // Where applies the entql predicate on the query filter. func (f *RevisionFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[11].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[12].Type, p, s); err != nil { s.AddError(err) } }) @@ -1313,7 +1454,7 @@ type SessionFilter struct { // Where applies the entql predicate on the query filter. func (f *SessionFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[12].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[13].Type, p, s); err != nil { s.AddError(err) } }) @@ -1367,7 +1508,7 @@ type TokenFilter struct { // Where applies the entql predicate on the query filter. func (f *TokenFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[13].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[14].Type, p, s); err != nil { s.AddError(err) } }) @@ -1426,7 +1567,7 @@ type UserFilter struct { // Where applies the entql predicate on the query filter. func (f *UserFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[14].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[15].Type, p, s); err != nil { s.AddError(err) } }) diff --git a/entc/integration/customid/ent/generate.go b/entc/integration/customid/ent/generate.go index 7d67bb6a8..227167fa0 100644 --- a/entc/integration/customid/ent/generate.go +++ b/entc/integration/customid/ent/generate.go @@ -4,4 +4,4 @@ package ent -//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert --feature entql --header "// Copyright 2019-present Facebook Inc. All rights reserved.\n// This source code is licensed under the Apache 2.0 license found\n// in the LICENSE file in the root directory of this source tree.\n\n// Code generated by ent, DO NOT EDIT." ./schema +//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert,privacy,entql --header "// Copyright 2019-present Facebook Inc. All rights reserved.\n// This source code is licensed under the Apache 2.0 license found\n// in the LICENSE file in the root directory of this source tree.\n\n// Code generated by ent, DO NOT EDIT." ./schema diff --git a/entc/integration/customid/ent/hook/hook.go b/entc/integration/customid/ent/hook/hook.go index bcce3353e..68dc453e9 100644 --- a/entc/integration/customid/ent/hook/hook.go +++ b/entc/integration/customid/ent/hook/hook.go @@ -39,6 +39,19 @@ func (f BlobFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) return f(ctx, mv) } +// The BlobLinkFunc type is an adapter to allow the use of ordinary +// function as BlobLink mutator. +type BlobLinkFunc func(context.Context, *ent.BlobLinkMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f BlobLinkFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.BlobLinkMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.BlobLinkMutation", m) + } + return f(ctx, mv) +} + // The CarFunc type is an adapter to allow the use of ordinary // function as Car mutator. type CarFunc func(context.Context, *ent.CarMutation) (ent.Value, error) diff --git a/entc/integration/customid/ent/migrate/schema.go b/entc/integration/customid/ent/migrate/schema.go index f4e33216f..b08f3bbed 100644 --- a/entc/integration/customid/ent/migrate/schema.go +++ b/entc/integration/customid/ent/migrate/schema.go @@ -44,6 +44,32 @@ var ( }, }, } + // BlobLinksColumns holds the columns for the "blob_links" table. + BlobLinksColumns = []*schema.Column{ + {Name: "created_at", Type: field.TypeTime}, + {Name: "blob_id", Type: field.TypeUUID}, + {Name: "link_id", Type: field.TypeUUID}, + } + // BlobLinksTable holds the schema information for the "blob_links" table. + BlobLinksTable = &schema.Table{ + Name: "blob_links", + Columns: BlobLinksColumns, + PrimaryKey: []*schema.Column{BlobLinksColumns[1], BlobLinksColumns[2]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "blob_links_blobs_blob", + Columns: []*schema.Column{BlobLinksColumns[1]}, + RefColumns: []*schema.Column{BlobsColumns[0]}, + OnDelete: schema.NoAction, + }, + { + Symbol: "blob_links_blobs_link", + Columns: []*schema.Column{BlobLinksColumns[2]}, + RefColumns: []*schema.Column{BlobsColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + } // CarsColumns holds the columns for the "cars" table. CarsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -292,31 +318,6 @@ var ( }, }, } - // BlobLinksColumns holds the columns for the "blob_links" table. - BlobLinksColumns = []*schema.Column{ - {Name: "blob_id", Type: field.TypeUUID}, - {Name: "link_id", Type: field.TypeUUID}, - } - // BlobLinksTable holds the schema information for the "blob_links" table. - BlobLinksTable = &schema.Table{ - Name: "blob_links", - Columns: BlobLinksColumns, - PrimaryKey: []*schema.Column{BlobLinksColumns[0], BlobLinksColumns[1]}, - ForeignKeys: []*schema.ForeignKey{ - { - Symbol: "blob_links_blob_id", - Columns: []*schema.Column{BlobLinksColumns[0]}, - RefColumns: []*schema.Column{BlobsColumns[0]}, - OnDelete: schema.Cascade, - }, - { - Symbol: "blob_links_link_id", - Columns: []*schema.Column{BlobLinksColumns[1]}, - RefColumns: []*schema.Column{BlobsColumns[0]}, - OnDelete: schema.Cascade, - }, - }, - } // GroupUsersColumns holds the columns for the "group_users" table. GroupUsersColumns = []*schema.Column{ {Name: "group_id", Type: field.TypeInt}, @@ -371,6 +372,7 @@ var ( Tables = []*schema.Table{ AccountsTable, BlobsTable, + BlobLinksTable, CarsTable, DevicesTable, DocsTable, @@ -384,7 +386,6 @@ var ( SessionsTable, TokensTable, UsersTable, - BlobLinksTable, GroupUsersTable, PetFriendsTable, } @@ -392,6 +393,8 @@ var ( func init() { BlobsTable.ForeignKeys[0].RefTable = BlobsTable + BlobLinksTable.ForeignKeys[0].RefTable = BlobsTable + BlobLinksTable.ForeignKeys[1].RefTable = BlobsTable CarsTable.ForeignKeys[0].RefTable = PetsTable DevicesTable.ForeignKeys[0].RefTable = SessionsTable DocsTable.ForeignKeys[0].RefTable = DocsTable @@ -402,8 +405,6 @@ func init() { SessionsTable.ForeignKeys[0].RefTable = DevicesTable TokensTable.ForeignKeys[0].RefTable = AccountsTable UsersTable.ForeignKeys[0].RefTable = UsersTable - BlobLinksTable.ForeignKeys[0].RefTable = BlobsTable - BlobLinksTable.ForeignKeys[1].RefTable = BlobsTable GroupUsersTable.ForeignKeys[0].RefTable = GroupsTable GroupUsersTable.ForeignKeys[1].RefTable = UsersTable PetFriendsTable.ForeignKeys[0].RefTable = PetsTable diff --git a/entc/integration/customid/ent/mutation.go b/entc/integration/customid/ent/mutation.go index d530f96ce..07258a4a5 100644 --- a/entc/integration/customid/ent/mutation.go +++ b/entc/integration/customid/ent/mutation.go @@ -11,9 +11,11 @@ import ( "errors" "fmt" "sync" + "time" "entgo.io/ent/entc/integration/customid/ent/account" "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" "entgo.io/ent/entc/integration/customid/ent/car" "entgo.io/ent/entc/integration/customid/ent/device" "entgo.io/ent/entc/integration/customid/ent/doc" @@ -44,6 +46,7 @@ const ( // Node types. TypeAccount = "Account" TypeBlob = "Blob" + TypeBlobLink = "BlobLink" TypeCar = "Car" TypeDevice = "Device" TypeDoc = "Doc" @@ -1028,6 +1031,405 @@ func (m *BlobMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Blob edge %s", name) } +// BlobLinkMutation represents an operation that mutates the BlobLink nodes in the graph. +type BlobLinkMutation struct { + config + op Op + typ string + created_at *time.Time + clearedFields map[string]struct{} + blob *uuid.UUID + clearedblob bool + link *uuid.UUID + clearedlink bool + done bool + oldValue func(context.Context) (*BlobLink, error) + predicates []predicate.BlobLink +} + +var _ ent.Mutation = (*BlobLinkMutation)(nil) + +// bloblinkOption allows management of the mutation configuration using functional options. +type bloblinkOption func(*BlobLinkMutation) + +// newBlobLinkMutation creates new mutation for the BlobLink entity. +func newBlobLinkMutation(c config, op Op, opts ...bloblinkOption) *BlobLinkMutation { + m := &BlobLinkMutation{ + config: c, + op: op, + typ: TypeBlobLink, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m BlobLinkMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m BlobLinkMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetCreatedAt sets the "created_at" field. +func (m *BlobLinkMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *BlobLinkMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *BlobLinkMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetBlobID sets the "blob_id" field. +func (m *BlobLinkMutation) SetBlobID(u uuid.UUID) { + m.blob = &u +} + +// BlobID returns the value of the "blob_id" field in the mutation. +func (m *BlobLinkMutation) BlobID() (r uuid.UUID, exists bool) { + v := m.blob + if v == nil { + return + } + return *v, true +} + +// ResetBlobID resets all changes to the "blob_id" field. +func (m *BlobLinkMutation) ResetBlobID() { + m.blob = nil +} + +// SetLinkID sets the "link_id" field. +func (m *BlobLinkMutation) SetLinkID(u uuid.UUID) { + m.link = &u +} + +// LinkID returns the value of the "link_id" field in the mutation. +func (m *BlobLinkMutation) LinkID() (r uuid.UUID, exists bool) { + v := m.link + if v == nil { + return + } + return *v, true +} + +// ResetLinkID resets all changes to the "link_id" field. +func (m *BlobLinkMutation) ResetLinkID() { + m.link = nil +} + +// ClearBlob clears the "blob" edge to the Blob entity. +func (m *BlobLinkMutation) ClearBlob() { + m.clearedblob = true +} + +// BlobCleared reports if the "blob" edge to the Blob entity was cleared. +func (m *BlobLinkMutation) BlobCleared() bool { + return m.clearedblob +} + +// BlobIDs returns the "blob" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// BlobID instead. It exists only for internal usage by the builders. +func (m *BlobLinkMutation) BlobIDs() (ids []uuid.UUID) { + if id := m.blob; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetBlob resets all changes to the "blob" edge. +func (m *BlobLinkMutation) ResetBlob() { + m.blob = nil + m.clearedblob = false +} + +// ClearLink clears the "link" edge to the Blob entity. +func (m *BlobLinkMutation) ClearLink() { + m.clearedlink = true +} + +// LinkCleared reports if the "link" edge to the Blob entity was cleared. +func (m *BlobLinkMutation) LinkCleared() bool { + return m.clearedlink +} + +// LinkIDs returns the "link" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// LinkID instead. It exists only for internal usage by the builders. +func (m *BlobLinkMutation) LinkIDs() (ids []uuid.UUID) { + if id := m.link; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetLink resets all changes to the "link" edge. +func (m *BlobLinkMutation) ResetLink() { + m.link = nil + m.clearedlink = false +} + +// Where appends a list predicates to the BlobLinkMutation builder. +func (m *BlobLinkMutation) Where(ps ...predicate.BlobLink) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *BlobLinkMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (BlobLink). +func (m *BlobLinkMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *BlobLinkMutation) Fields() []string { + fields := make([]string, 0, 3) + if m.created_at != nil { + fields = append(fields, bloblink.FieldCreatedAt) + } + if m.blob != nil { + fields = append(fields, bloblink.FieldBlobID) + } + if m.link != nil { + fields = append(fields, bloblink.FieldLinkID) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *BlobLinkMutation) Field(name string) (ent.Value, bool) { + switch name { + case bloblink.FieldCreatedAt: + return m.CreatedAt() + case bloblink.FieldBlobID: + return m.BlobID() + case bloblink.FieldLinkID: + return m.LinkID() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *BlobLinkMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + return nil, errors.New("edge schema BlobLink does not support getting old values") +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *BlobLinkMutation) SetField(name string, value ent.Value) error { + switch name { + case bloblink.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case bloblink.FieldBlobID: + v, ok := value.(uuid.UUID) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetBlobID(v) + return nil + case bloblink.FieldLinkID: + v, ok := value.(uuid.UUID) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLinkID(v) + return nil + } + return fmt.Errorf("unknown BlobLink field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *BlobLinkMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *BlobLinkMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *BlobLinkMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown BlobLink numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *BlobLinkMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *BlobLinkMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *BlobLinkMutation) ClearField(name string) error { + return fmt.Errorf("unknown BlobLink nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *BlobLinkMutation) ResetField(name string) error { + switch name { + case bloblink.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case bloblink.FieldBlobID: + m.ResetBlobID() + return nil + case bloblink.FieldLinkID: + m.ResetLinkID() + return nil + } + return fmt.Errorf("unknown BlobLink field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *BlobLinkMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.blob != nil { + edges = append(edges, bloblink.EdgeBlob) + } + if m.link != nil { + edges = append(edges, bloblink.EdgeLink) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *BlobLinkMutation) AddedIDs(name string) []ent.Value { + switch name { + case bloblink.EdgeBlob: + if id := m.blob; id != nil { + return []ent.Value{*id} + } + case bloblink.EdgeLink: + if id := m.link; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *BlobLinkMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *BlobLinkMutation) RemovedIDs(name string) []ent.Value { + switch name { + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *BlobLinkMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.clearedblob { + edges = append(edges, bloblink.EdgeBlob) + } + if m.clearedlink { + edges = append(edges, bloblink.EdgeLink) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *BlobLinkMutation) EdgeCleared(name string) bool { + switch name { + case bloblink.EdgeBlob: + return m.clearedblob + case bloblink.EdgeLink: + return m.clearedlink + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *BlobLinkMutation) ClearEdge(name string) error { + switch name { + case bloblink.EdgeBlob: + m.ClearBlob() + return nil + case bloblink.EdgeLink: + m.ClearLink() + return nil + } + return fmt.Errorf("unknown BlobLink unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *BlobLinkMutation) ResetEdge(name string) error { + switch name { + case bloblink.EdgeBlob: + m.ResetBlob() + return nil + case bloblink.EdgeLink: + m.ResetLink() + return nil + } + return fmt.Errorf("unknown BlobLink edge %s", name) +} + // CarMutation represents an operation that mutates the Car nodes in the graph. type CarMutation struct { config diff --git a/entc/integration/customid/ent/predicate/predicate.go b/entc/integration/customid/ent/predicate/predicate.go index a41f9b661..d5e7034fc 100644 --- a/entc/integration/customid/ent/predicate/predicate.go +++ b/entc/integration/customid/ent/predicate/predicate.go @@ -16,6 +16,9 @@ type Account func(*sql.Selector) // Blob is the predicate function for blob builders. type Blob func(*sql.Selector) +// BlobLink is the predicate function for bloblink builders. +type BlobLink func(*sql.Selector) + // Car is the predicate function for car builders. type Car func(*sql.Selector) diff --git a/entc/integration/customid/ent/privacy/privacy.go b/entc/integration/customid/ent/privacy/privacy.go new file mode 100644 index 000000000..ec8b92858 --- /dev/null +++ b/entc/integration/customid/ent/privacy/privacy.go @@ -0,0 +1,650 @@ +// Copyright 2019-present Facebook Inc. 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 ent, DO NOT EDIT. + +package privacy + +import ( + "context" + "fmt" + + "entgo.io/ent/entc/integration/customid/ent" + "entgo.io/ent/entql" + + "entgo.io/ent/privacy" +) + +var ( + // Allow may be returned by rules to indicate that the policy + // evaluation should terminate with allow decision. + Allow = privacy.Allow + + // Deny may be returned by rules to indicate that the policy + // evaluation should terminate with deny decision. + Deny = privacy.Deny + + // Skip may be returned by rules to indicate that the policy + // evaluation should continue to the next rule. + Skip = privacy.Skip +) + +// Allowf returns an formatted wrapped Allow decision. +func Allowf(format string, a ...interface{}) error { + return fmt.Errorf(format+": %w", append(a, Allow)...) +} + +// Denyf returns an formatted wrapped Deny decision. +func Denyf(format string, a ...interface{}) error { + return fmt.Errorf(format+": %w", append(a, Deny)...) +} + +// Skipf returns an formatted wrapped Skip decision. +func Skipf(format string, a ...interface{}) error { + return fmt.Errorf(format+": %w", append(a, Skip)...) +} + +// DecisionContext creates a new context from the given parent context with +// a policy decision attach to it. +func DecisionContext(parent context.Context, decision error) context.Context { + return privacy.DecisionContext(parent, decision) +} + +// DecisionFromContext retrieves the policy decision from the context. +func DecisionFromContext(ctx context.Context) (error, bool) { + return privacy.DecisionFromContext(ctx) +} + +type ( + // Policy groups query and mutation policies. + Policy = privacy.Policy + + // QueryRule defines the interface deciding whether a + // query is allowed and optionally modify it. + QueryRule = privacy.QueryRule + // QueryPolicy combines multiple query rules into a single policy. + QueryPolicy = privacy.QueryPolicy + + // MutationRule defines the interface which decides whether a + // mutation is allowed and optionally modifies it. + MutationRule = privacy.MutationRule + // MutationPolicy combines multiple mutation rules into a single policy. + MutationPolicy = privacy.MutationPolicy +) + +// QueryRuleFunc type is an adapter to allow the use of +// ordinary functions as query rules. +type QueryRuleFunc func(context.Context, ent.Query) error + +// Eval returns f(ctx, q). +func (f QueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + return f(ctx, q) +} + +// MutationRuleFunc type is an adapter which allows the use of +// ordinary functions as mutation rules. +type MutationRuleFunc func(context.Context, ent.Mutation) error + +// EvalMutation returns f(ctx, m). +func (f MutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + return f(ctx, m) +} + +// QueryMutationRule is an interface which groups query and mutation rules. +type QueryMutationRule interface { + QueryRule + MutationRule +} + +// AlwaysAllowRule returns a rule that returns an allow decision. +func AlwaysAllowRule() QueryMutationRule { + return fixedDecision{Allow} +} + +// AlwaysDenyRule returns a rule that returns a deny decision. +func AlwaysDenyRule() QueryMutationRule { + return fixedDecision{Deny} +} + +type fixedDecision struct { + decision error +} + +func (f fixedDecision) EvalQuery(context.Context, ent.Query) error { + return f.decision +} + +func (f fixedDecision) EvalMutation(context.Context, ent.Mutation) error { + return f.decision +} + +type contextDecision struct { + eval func(context.Context) error +} + +// ContextQueryMutationRule creates a query/mutation rule from a context eval func. +func ContextQueryMutationRule(eval func(context.Context) error) QueryMutationRule { + return contextDecision{eval} +} + +func (c contextDecision) EvalQuery(ctx context.Context, _ ent.Query) error { + return c.eval(ctx) +} + +func (c contextDecision) EvalMutation(ctx context.Context, _ ent.Mutation) error { + return c.eval(ctx) +} + +// OnMutationOperation evaluates the given rule only on a given mutation operation. +func OnMutationOperation(rule MutationRule, op ent.Op) MutationRule { + return MutationRuleFunc(func(ctx context.Context, m ent.Mutation) error { + if m.Op().Is(op) { + return rule.EvalMutation(ctx, m) + } + return Skip + }) +} + +// DenyMutationOperationRule returns a rule denying specified mutation operation. +func DenyMutationOperationRule(op ent.Op) MutationRule { + rule := MutationRuleFunc(func(_ context.Context, m ent.Mutation) error { + return Denyf("ent/privacy: operation %s is not allowed", m.Op()) + }) + return OnMutationOperation(rule, op) +} + +// The AccountQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type AccountQueryRuleFunc func(context.Context, *ent.AccountQuery) error + +// EvalQuery return f(ctx, q). +func (f AccountQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.AccountQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.AccountQuery", q) +} + +// The AccountMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type AccountMutationRuleFunc func(context.Context, *ent.AccountMutation) error + +// EvalMutation calls f(ctx, m). +func (f AccountMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.AccountMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.AccountMutation", m) +} + +// The BlobQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type BlobQueryRuleFunc func(context.Context, *ent.BlobQuery) error + +// EvalQuery return f(ctx, q). +func (f BlobQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.BlobQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.BlobQuery", q) +} + +// The BlobMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type BlobMutationRuleFunc func(context.Context, *ent.BlobMutation) error + +// EvalMutation calls f(ctx, m). +func (f BlobMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.BlobMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.BlobMutation", m) +} + +// The BlobLinkQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type BlobLinkQueryRuleFunc func(context.Context, *ent.BlobLinkQuery) error + +// EvalQuery return f(ctx, q). +func (f BlobLinkQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.BlobLinkQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.BlobLinkQuery", q) +} + +// The BlobLinkMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type BlobLinkMutationRuleFunc func(context.Context, *ent.BlobLinkMutation) error + +// EvalMutation calls f(ctx, m). +func (f BlobLinkMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.BlobLinkMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.BlobLinkMutation", m) +} + +// The CarQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type CarQueryRuleFunc func(context.Context, *ent.CarQuery) error + +// EvalQuery return f(ctx, q). +func (f CarQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.CarQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.CarQuery", q) +} + +// The CarMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type CarMutationRuleFunc func(context.Context, *ent.CarMutation) error + +// EvalMutation calls f(ctx, m). +func (f CarMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.CarMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.CarMutation", m) +} + +// The DeviceQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type DeviceQueryRuleFunc func(context.Context, *ent.DeviceQuery) error + +// EvalQuery return f(ctx, q). +func (f DeviceQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.DeviceQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.DeviceQuery", q) +} + +// The DeviceMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type DeviceMutationRuleFunc func(context.Context, *ent.DeviceMutation) error + +// EvalMutation calls f(ctx, m). +func (f DeviceMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.DeviceMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.DeviceMutation", m) +} + +// The DocQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type DocQueryRuleFunc func(context.Context, *ent.DocQuery) error + +// EvalQuery return f(ctx, q). +func (f DocQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.DocQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.DocQuery", q) +} + +// The DocMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type DocMutationRuleFunc func(context.Context, *ent.DocMutation) error + +// EvalMutation calls f(ctx, m). +func (f DocMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.DocMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.DocMutation", m) +} + +// The GroupQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type GroupQueryRuleFunc func(context.Context, *ent.GroupQuery) error + +// EvalQuery return f(ctx, q). +func (f GroupQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.GroupQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.GroupQuery", q) +} + +// The GroupMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type GroupMutationRuleFunc func(context.Context, *ent.GroupMutation) error + +// EvalMutation calls f(ctx, m). +func (f GroupMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.GroupMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.GroupMutation", m) +} + +// The IntSIDQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type IntSIDQueryRuleFunc func(context.Context, *ent.IntSIDQuery) error + +// EvalQuery return f(ctx, q). +func (f IntSIDQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.IntSIDQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.IntSIDQuery", q) +} + +// The IntSIDMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type IntSIDMutationRuleFunc func(context.Context, *ent.IntSIDMutation) error + +// EvalMutation calls f(ctx, m). +func (f IntSIDMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.IntSIDMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.IntSIDMutation", m) +} + +// The MixinIDQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type MixinIDQueryRuleFunc func(context.Context, *ent.MixinIDQuery) error + +// EvalQuery return f(ctx, q). +func (f MixinIDQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.MixinIDQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.MixinIDQuery", q) +} + +// The MixinIDMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type MixinIDMutationRuleFunc func(context.Context, *ent.MixinIDMutation) error + +// EvalMutation calls f(ctx, m). +func (f MixinIDMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.MixinIDMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.MixinIDMutation", m) +} + +// The NoteQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type NoteQueryRuleFunc func(context.Context, *ent.NoteQuery) error + +// EvalQuery return f(ctx, q). +func (f NoteQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.NoteQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.NoteQuery", q) +} + +// The NoteMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type NoteMutationRuleFunc func(context.Context, *ent.NoteMutation) error + +// EvalMutation calls f(ctx, m). +func (f NoteMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.NoteMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.NoteMutation", m) +} + +// The OtherQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type OtherQueryRuleFunc func(context.Context, *ent.OtherQuery) error + +// EvalQuery return f(ctx, q). +func (f OtherQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.OtherQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.OtherQuery", q) +} + +// The OtherMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type OtherMutationRuleFunc func(context.Context, *ent.OtherMutation) error + +// EvalMutation calls f(ctx, m). +func (f OtherMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.OtherMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.OtherMutation", m) +} + +// The PetQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type PetQueryRuleFunc func(context.Context, *ent.PetQuery) error + +// EvalQuery return f(ctx, q). +func (f PetQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.PetQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.PetQuery", q) +} + +// The PetMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type PetMutationRuleFunc func(context.Context, *ent.PetMutation) error + +// EvalMutation calls f(ctx, m). +func (f PetMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.PetMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.PetMutation", m) +} + +// The RevisionQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type RevisionQueryRuleFunc func(context.Context, *ent.RevisionQuery) error + +// EvalQuery return f(ctx, q). +func (f RevisionQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.RevisionQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.RevisionQuery", q) +} + +// The RevisionMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type RevisionMutationRuleFunc func(context.Context, *ent.RevisionMutation) error + +// EvalMutation calls f(ctx, m). +func (f RevisionMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.RevisionMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.RevisionMutation", m) +} + +// The SessionQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type SessionQueryRuleFunc func(context.Context, *ent.SessionQuery) error + +// EvalQuery return f(ctx, q). +func (f SessionQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.SessionQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.SessionQuery", q) +} + +// The SessionMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type SessionMutationRuleFunc func(context.Context, *ent.SessionMutation) error + +// EvalMutation calls f(ctx, m). +func (f SessionMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.SessionMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.SessionMutation", m) +} + +// The TokenQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type TokenQueryRuleFunc func(context.Context, *ent.TokenQuery) error + +// EvalQuery return f(ctx, q). +func (f TokenQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.TokenQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.TokenQuery", q) +} + +// The TokenMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type TokenMutationRuleFunc func(context.Context, *ent.TokenMutation) error + +// EvalMutation calls f(ctx, m). +func (f TokenMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.TokenMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.TokenMutation", m) +} + +// The UserQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type UserQueryRuleFunc func(context.Context, *ent.UserQuery) error + +// EvalQuery return f(ctx, q). +func (f UserQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.UserQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.UserQuery", q) +} + +// The UserMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type UserMutationRuleFunc func(context.Context, *ent.UserMutation) error + +// EvalMutation calls f(ctx, m). +func (f UserMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.UserMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.UserMutation", m) +} + +type ( + // Filter is the interface that wraps the Where function + // for filtering nodes in queries and mutations. + Filter interface { + // Where applies a filter on the executed query/mutation. + Where(entql.P) + } + + // The FilterFunc type is an adapter that allows the use of ordinary + // functions as filters for query and mutation types. + FilterFunc func(context.Context, Filter) error +) + +// EvalQuery calls f(ctx, q) if the query implements the Filter interface, otherwise it is denied. +func (f FilterFunc) EvalQuery(ctx context.Context, q ent.Query) error { + fr, err := queryFilter(q) + if err != nil { + return err + } + return f(ctx, fr) +} + +// EvalMutation calls f(ctx, q) if the mutation implements the Filter interface, otherwise it is denied. +func (f FilterFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + fr, err := mutationFilter(m) + if err != nil { + return err + } + return f(ctx, fr) +} + +var _ QueryMutationRule = FilterFunc(nil) + +func queryFilter(q ent.Query) (Filter, error) { + switch q := q.(type) { + case *ent.AccountQuery: + return q.Filter(), nil + case *ent.BlobQuery: + return q.Filter(), nil + case *ent.BlobLinkQuery: + return q.Filter(), nil + case *ent.CarQuery: + return q.Filter(), nil + case *ent.DeviceQuery: + return q.Filter(), nil + case *ent.DocQuery: + return q.Filter(), nil + case *ent.GroupQuery: + return q.Filter(), nil + case *ent.IntSIDQuery: + return q.Filter(), nil + case *ent.MixinIDQuery: + return q.Filter(), nil + case *ent.NoteQuery: + return q.Filter(), nil + case *ent.OtherQuery: + return q.Filter(), nil + case *ent.PetQuery: + return q.Filter(), nil + case *ent.RevisionQuery: + return q.Filter(), nil + case *ent.SessionQuery: + return q.Filter(), nil + case *ent.TokenQuery: + return q.Filter(), nil + case *ent.UserQuery: + return q.Filter(), nil + default: + return nil, Denyf("ent/privacy: unexpected query type %T for query filter", q) + } +} + +func mutationFilter(m ent.Mutation) (Filter, error) { + switch m := m.(type) { + case *ent.AccountMutation: + return m.Filter(), nil + case *ent.BlobMutation: + return m.Filter(), nil + case *ent.BlobLinkMutation: + return m.Filter(), nil + case *ent.CarMutation: + return m.Filter(), nil + case *ent.DeviceMutation: + return m.Filter(), nil + case *ent.DocMutation: + return m.Filter(), nil + case *ent.GroupMutation: + return m.Filter(), nil + case *ent.IntSIDMutation: + return m.Filter(), nil + case *ent.MixinIDMutation: + return m.Filter(), nil + case *ent.NoteMutation: + return m.Filter(), nil + case *ent.OtherMutation: + return m.Filter(), nil + case *ent.PetMutation: + return m.Filter(), nil + case *ent.RevisionMutation: + return m.Filter(), nil + case *ent.SessionMutation: + return m.Filter(), nil + case *ent.TokenMutation: + return m.Filter(), nil + case *ent.UserMutation: + return m.Filter(), nil + default: + return nil, Denyf("ent/privacy: unexpected mutation type %T for mutation filter", m) + } +} diff --git a/entc/integration/customid/ent/runtime.go b/entc/integration/customid/ent/runtime.go index c6252b676..b31e3ea18 100644 --- a/entc/integration/customid/ent/runtime.go +++ b/entc/integration/customid/ent/runtime.go @@ -7,8 +7,11 @@ package ent import ( + "time" + "entgo.io/ent/entc/integration/customid/ent/account" "entgo.io/ent/entc/integration/customid/ent/blob" + "entgo.io/ent/entc/integration/customid/ent/bloblink" "entgo.io/ent/entc/integration/customid/ent/car" "entgo.io/ent/entc/integration/customid/ent/device" "entgo.io/ent/entc/integration/customid/ent/doc" @@ -51,6 +54,12 @@ func init() { blobDescID := blobFields[0].Descriptor() // blob.DefaultID holds the default value on creation for the id field. blob.DefaultID = blobDescID.Default.(func() uuid.UUID) + bloblinkFields := schema.BlobLink{}.Fields() + _ = bloblinkFields + // bloblinkDescCreatedAt is the schema descriptor for created_at field. + bloblinkDescCreatedAt := bloblinkFields[0].Descriptor() + // bloblink.DefaultCreatedAt holds the default value on creation for the created_at field. + bloblink.DefaultCreatedAt = bloblinkDescCreatedAt.Default.(func() time.Time) carMixin := schema.Car{}.Mixin() carMixinFields0 := carMixin[0].Fields() _ = carMixinFields0 diff --git a/entc/integration/customid/ent/schema/blob.go b/entc/integration/customid/ent/schema/blob.go index 3bf940448..5f5cf6f57 100644 --- a/entc/integration/customid/ent/schema/blob.go +++ b/entc/integration/customid/ent/schema/blob.go @@ -5,6 +5,10 @@ package schema import ( + "time" + + "entgo.io/ent/schema" + "entgo.io/ent" "entgo.io/ent/dialect/entsql" "entgo.io/ent/schema/edge" @@ -40,6 +44,43 @@ func (Blob) Edges() []ent.Edge { return []ent.Edge{ edge.To("parent", Blob.Type). Unique(), - edge.To("links", Blob.Type), + edge.To("links", Blob.Type). + Through("blob_links", BlobLink.Type), + } +} + +// BlobLink holds the edge schema definition for blob links. +type BlobLink struct { + ent.Schema +} + +// Annotations of the BlobLink. +func (BlobLink) Annotations() []schema.Annotation { + return []schema.Annotation{ + field.ID("blob_id", "link_id"), + } +} + +// Fields of the BlobLink. +func (BlobLink) Fields() []ent.Field { + return []ent.Field{ + field.Time("created_at"). + Default(time.Now), + field.UUID("blob_id", uuid.UUID{}), + field.UUID("link_id", uuid.UUID{}), + } +} + +// Edges of the BlobLink. +func (BlobLink) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("blob", Blob.Type). + Field("blob_id"). + Required(). + Unique(), + edge.To("link", Blob.Type). + Field("link_id"). + Required(). + Unique(), } } diff --git a/entc/integration/customid/ent/tx.go b/entc/integration/customid/ent/tx.go index cdfd32d66..a682fca1a 100644 --- a/entc/integration/customid/ent/tx.go +++ b/entc/integration/customid/ent/tx.go @@ -20,6 +20,8 @@ type Tx struct { Account *AccountClient // Blob is the client for interacting with the Blob builders. Blob *BlobClient + // BlobLink is the client for interacting with the BlobLink builders. + BlobLink *BlobLinkClient // Car is the client for interacting with the Car builders. Car *CarClient // Device is the client for interacting with the Device builders. @@ -183,6 +185,7 @@ func (tx *Tx) Client() *Client { func (tx *Tx) init() { tx.Account = NewAccountClient(tx.config) tx.Blob = NewBlobClient(tx.config) + tx.BlobLink = NewBlobLinkClient(tx.config) tx.Car = NewCarClient(tx.config) tx.Device = NewDeviceClient(tx.config) tx.Doc = NewDocClient(tx.config) diff --git a/entc/integration/edgeschema/edgeschema_test.go b/entc/integration/edgeschema/edgeschema_test.go index a84de9186..33c50bb05 100644 --- a/entc/integration/edgeschema/edgeschema_test.go +++ b/entc/integration/edgeschema/edgeschema_test.go @@ -15,6 +15,7 @@ import ( "entgo.io/ent/entc/integration/edgeschema/ent/group" "entgo.io/ent/entc/integration/edgeschema/ent/migrate" "entgo.io/ent/entc/integration/edgeschema/ent/relationship" + _ "entgo.io/ent/entc/integration/edgeschema/ent/runtime" "entgo.io/ent/entc/integration/edgeschema/ent/tweetlike" "entgo.io/ent/entc/integration/edgeschema/ent/user" diff --git a/entc/integration/edgeschema/ent/client.go b/entc/integration/edgeschema/ent/client.go index c63cb23eb..404adf1ff 100644 --- a/entc/integration/edgeschema/ent/client.go +++ b/entc/integration/edgeschema/ent/client.go @@ -990,7 +990,8 @@ func (c *TweetLikeClient) QueryUser(tl *TweetLike) *UserQuery { // Hooks returns the client hooks. func (c *TweetLikeClient) Hooks() []Hook { - return c.hooks.TweetLike + hooks := c.hooks.TweetLike + return append(hooks[:len(hooks):len(hooks)], tweetlike.Hooks[:]...) } // TweetTagClient is a client for the TweetTag schema. diff --git a/entc/integration/edgeschema/ent/runtime.go b/entc/integration/edgeschema/ent/runtime.go index 47472a193..7e89926e9 100644 --- a/entc/integration/edgeschema/ent/runtime.go +++ b/entc/integration/edgeschema/ent/runtime.go @@ -6,79 +6,4 @@ package ent -import ( - "time" - - "entgo.io/ent/entc/integration/edgeschema/ent/friendship" - "entgo.io/ent/entc/integration/edgeschema/ent/group" - "entgo.io/ent/entc/integration/edgeschema/ent/relationship" - "entgo.io/ent/entc/integration/edgeschema/ent/schema" - "entgo.io/ent/entc/integration/edgeschema/ent/tweetlike" - "entgo.io/ent/entc/integration/edgeschema/ent/tweettag" - "entgo.io/ent/entc/integration/edgeschema/ent/user" - "entgo.io/ent/entc/integration/edgeschema/ent/usergroup" - "entgo.io/ent/entc/integration/edgeschema/ent/usertweet" - "github.com/google/uuid" -) - -// The init function reads all schema descriptors with runtime code -// (default values, validators, hooks and policies) and stitches it -// to their package variables. -func init() { - friendshipFields := schema.Friendship{}.Fields() - _ = friendshipFields - // friendshipDescWeight is the schema descriptor for weight field. - friendshipDescWeight := friendshipFields[0].Descriptor() - // friendship.DefaultWeight holds the default value on creation for the weight field. - friendship.DefaultWeight = friendshipDescWeight.Default.(int) - // friendshipDescCreatedAt is the schema descriptor for created_at field. - friendshipDescCreatedAt := friendshipFields[1].Descriptor() - // friendship.DefaultCreatedAt holds the default value on creation for the created_at field. - friendship.DefaultCreatedAt = friendshipDescCreatedAt.Default.(func() time.Time) - groupFields := schema.Group{}.Fields() - _ = groupFields - // groupDescName is the schema descriptor for name field. - groupDescName := groupFields[0].Descriptor() - // group.DefaultName holds the default value on creation for the name field. - group.DefaultName = groupDescName.Default.(string) - relationshipFields := schema.Relationship{}.Fields() - _ = relationshipFields - // relationshipDescWeight is the schema descriptor for weight field. - relationshipDescWeight := relationshipFields[0].Descriptor() - // relationship.DefaultWeight holds the default value on creation for the weight field. - relationship.DefaultWeight = relationshipDescWeight.Default.(int) - tweetlikeFields := schema.TweetLike{}.Fields() - _ = tweetlikeFields - // tweetlikeDescLikedAt is the schema descriptor for liked_at field. - tweetlikeDescLikedAt := tweetlikeFields[0].Descriptor() - // tweetlike.DefaultLikedAt holds the default value on creation for the liked_at field. - tweetlike.DefaultLikedAt = tweetlikeDescLikedAt.Default.(func() time.Time) - tweettagFields := schema.TweetTag{}.Fields() - _ = tweettagFields - // tweettagDescAddedAt is the schema descriptor for added_at field. - tweettagDescAddedAt := tweettagFields[1].Descriptor() - // tweettag.DefaultAddedAt holds the default value on creation for the added_at field. - tweettag.DefaultAddedAt = tweettagDescAddedAt.Default.(func() time.Time) - // tweettagDescID is the schema descriptor for id field. - tweettagDescID := tweettagFields[0].Descriptor() - // tweettag.DefaultID holds the default value on creation for the id field. - tweettag.DefaultID = tweettagDescID.Default.(func() uuid.UUID) - userFields := schema.User{}.Fields() - _ = userFields - // userDescName is the schema descriptor for name field. - userDescName := userFields[0].Descriptor() - // user.DefaultName holds the default value on creation for the name field. - user.DefaultName = userDescName.Default.(string) - usergroupFields := schema.UserGroup{}.Fields() - _ = usergroupFields - // usergroupDescJoinedAt is the schema descriptor for joined_at field. - usergroupDescJoinedAt := usergroupFields[0].Descriptor() - // usergroup.DefaultJoinedAt holds the default value on creation for the joined_at field. - usergroup.DefaultJoinedAt = usergroupDescJoinedAt.Default.(func() time.Time) - usertweetFields := schema.UserTweet{}.Fields() - _ = usertweetFields - // usertweetDescCreatedAt is the schema descriptor for created_at field. - usertweetDescCreatedAt := usertweetFields[0].Descriptor() - // usertweet.DefaultCreatedAt holds the default value on creation for the created_at field. - usertweet.DefaultCreatedAt = usertweetDescCreatedAt.Default.(func() time.Time) -} +// The schema-stitching logic is generated in entgo.io/ent/entc/integration/edgeschema/ent/runtime/runtime.go diff --git a/entc/integration/edgeschema/ent/runtime/runtime.go b/entc/integration/edgeschema/ent/runtime/runtime.go index 887be4461..e16ce3030 100644 --- a/entc/integration/edgeschema/ent/runtime/runtime.go +++ b/entc/integration/edgeschema/ent/runtime/runtime.go @@ -6,7 +6,95 @@ package runtime -// The schema-stitching logic is generated in entgo.io/ent/entc/integration/edgeschema/ent/runtime.go +import ( + "context" + "time" + + "entgo.io/ent/entc/integration/edgeschema/ent/friendship" + "entgo.io/ent/entc/integration/edgeschema/ent/group" + "entgo.io/ent/entc/integration/edgeschema/ent/relationship" + "entgo.io/ent/entc/integration/edgeschema/ent/schema" + "entgo.io/ent/entc/integration/edgeschema/ent/tweetlike" + "entgo.io/ent/entc/integration/edgeschema/ent/tweettag" + "entgo.io/ent/entc/integration/edgeschema/ent/user" + "entgo.io/ent/entc/integration/edgeschema/ent/usergroup" + "entgo.io/ent/entc/integration/edgeschema/ent/usertweet" + "github.com/google/uuid" + + "entgo.io/ent" + "entgo.io/ent/privacy" +) + +// The init function reads all schema descriptors with runtime code +// (default values, validators, hooks and policies) and stitches it +// to their package variables. +func init() { + friendshipFields := schema.Friendship{}.Fields() + _ = friendshipFields + // friendshipDescWeight is the schema descriptor for weight field. + friendshipDescWeight := friendshipFields[0].Descriptor() + // friendship.DefaultWeight holds the default value on creation for the weight field. + friendship.DefaultWeight = friendshipDescWeight.Default.(int) + // friendshipDescCreatedAt is the schema descriptor for created_at field. + friendshipDescCreatedAt := friendshipFields[1].Descriptor() + // friendship.DefaultCreatedAt holds the default value on creation for the created_at field. + friendship.DefaultCreatedAt = friendshipDescCreatedAt.Default.(func() time.Time) + groupFields := schema.Group{}.Fields() + _ = groupFields + // groupDescName is the schema descriptor for name field. + groupDescName := groupFields[0].Descriptor() + // group.DefaultName holds the default value on creation for the name field. + group.DefaultName = groupDescName.Default.(string) + relationshipFields := schema.Relationship{}.Fields() + _ = relationshipFields + // relationshipDescWeight is the schema descriptor for weight field. + relationshipDescWeight := relationshipFields[0].Descriptor() + // relationship.DefaultWeight holds the default value on creation for the weight field. + relationship.DefaultWeight = relationshipDescWeight.Default.(int) + tweetlike.Policy = privacy.NewPolicies(schema.TweetLike{}) + tweetlike.Hooks[0] = func(next ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if err := tweetlike.Policy.EvalMutation(ctx, m); err != nil { + return nil, err + } + return next.Mutate(ctx, m) + }) + } + tweetlikeFields := schema.TweetLike{}.Fields() + _ = tweetlikeFields + // tweetlikeDescLikedAt is the schema descriptor for liked_at field. + tweetlikeDescLikedAt := tweetlikeFields[0].Descriptor() + // tweetlike.DefaultLikedAt holds the default value on creation for the liked_at field. + tweetlike.DefaultLikedAt = tweetlikeDescLikedAt.Default.(func() time.Time) + tweettagFields := schema.TweetTag{}.Fields() + _ = tweettagFields + // tweettagDescAddedAt is the schema descriptor for added_at field. + tweettagDescAddedAt := tweettagFields[1].Descriptor() + // tweettag.DefaultAddedAt holds the default value on creation for the added_at field. + tweettag.DefaultAddedAt = tweettagDescAddedAt.Default.(func() time.Time) + // tweettagDescID is the schema descriptor for id field. + tweettagDescID := tweettagFields[0].Descriptor() + // tweettag.DefaultID holds the default value on creation for the id field. + tweettag.DefaultID = tweettagDescID.Default.(func() uuid.UUID) + userFields := schema.User{}.Fields() + _ = userFields + // userDescName is the schema descriptor for name field. + userDescName := userFields[0].Descriptor() + // user.DefaultName holds the default value on creation for the name field. + user.DefaultName = userDescName.Default.(string) + usergroupFields := schema.UserGroup{}.Fields() + _ = usergroupFields + // usergroupDescJoinedAt is the schema descriptor for joined_at field. + usergroupDescJoinedAt := usergroupFields[0].Descriptor() + // usergroup.DefaultJoinedAt holds the default value on creation for the joined_at field. + usergroup.DefaultJoinedAt = usergroupDescJoinedAt.Default.(func() time.Time) + usertweetFields := schema.UserTweet{}.Fields() + _ = usertweetFields + // usertweetDescCreatedAt is the schema descriptor for created_at field. + usertweetDescCreatedAt := usertweetFields[0].Descriptor() + // usertweet.DefaultCreatedAt holds the default value on creation for the created_at field. + usertweet.DefaultCreatedAt = usertweetDescCreatedAt.Default.(func() time.Time) +} const ( Version = "(devel)" // Version of ent codegen. diff --git a/entc/integration/edgeschema/ent/schema/tweetlike.go b/entc/integration/edgeschema/ent/schema/tweetlike.go index 49c56ecdd..27b3aeef8 100644 --- a/entc/integration/edgeschema/ent/schema/tweetlike.go +++ b/entc/integration/edgeschema/ent/schema/tweetlike.go @@ -8,6 +8,7 @@ import ( "time" "entgo.io/ent" + "entgo.io/ent/entc/integration/privacy/ent/privacy" "entgo.io/ent/schema" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" @@ -47,3 +48,15 @@ func (TweetLike) Edges() []ent.Edge { Field("user_id"), } } + +// Policy defines the privacy policy of the TweetLike. +func (TweetLike) Policy() ent.Policy { + return privacy.Policy{ + Mutation: privacy.MutationPolicy{ + privacy.AlwaysAllowRule(), + }, + Query: privacy.QueryPolicy{ + privacy.AlwaysAllowRule(), + }, + } +} diff --git a/entc/integration/edgeschema/ent/tweetlike/tweetlike.go b/entc/integration/edgeschema/ent/tweetlike/tweetlike.go index 9b1f849a8..b1d1317ee 100644 --- a/entc/integration/edgeschema/ent/tweetlike/tweetlike.go +++ b/entc/integration/edgeschema/ent/tweetlike/tweetlike.go @@ -8,6 +8,8 @@ package tweetlike import ( "time" + + "entgo.io/ent" ) const ( @@ -62,7 +64,15 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "entgo.io/ent/entc/integration/edgeschema/ent/runtime" +// var ( + Hooks [1]ent.Hook + Policy ent.Policy // DefaultLikedAt holds the default value on creation for the "liked_at" field. DefaultLikedAt func() time.Time ) diff --git a/entc/integration/edgeschema/ent/tweetlike_create.go b/entc/integration/edgeschema/ent/tweetlike_create.go index a8134e466..854d99377 100644 --- a/entc/integration/edgeschema/ent/tweetlike_create.go +++ b/entc/integration/edgeschema/ent/tweetlike_create.go @@ -75,7 +75,9 @@ func (tlc *TweetLikeCreate) Save(ctx context.Context) (*TweetLike, error) { err error node *TweetLike ) - tlc.defaults() + if err := tlc.defaults(); err != nil { + return nil, err + } if len(tlc.hooks) == 0 { if err = tlc.check(); err != nil { return nil, err @@ -138,11 +140,15 @@ func (tlc *TweetLikeCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (tlc *TweetLikeCreate) defaults() { +func (tlc *TweetLikeCreate) defaults() error { if _, ok := tlc.mutation.LikedAt(); !ok { + if tweetlike.DefaultLikedAt == nil { + return fmt.Errorf("ent: uninitialized tweetlike.DefaultLikedAt (forgotten import ent/runtime?)") + } v := tweetlike.DefaultLikedAt() tlc.mutation.SetLikedAt(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/entc/integration/edgeschema/ent/tweetlike_query.go b/entc/integration/edgeschema/ent/tweetlike_query.go index b495dbf05..387cfe375 100644 --- a/entc/integration/edgeschema/ent/tweetlike_query.go +++ b/entc/integration/edgeschema/ent/tweetlike_query.go @@ -8,6 +8,7 @@ package ent import ( "context" + "errors" "fmt" "math" @@ -317,6 +318,12 @@ func (tlq *TweetLikeQuery) prepareQuery(ctx context.Context) error { } tlq.sql = prev } + if tweetlike.Policy == nil { + return errors.New("ent: uninitialized tweetlike.Policy (forgotten import ent/runtime?)") + } + if err := tweetlike.Policy.EvalQuery(ctx, tlq); err != nil { + return err + } return nil }