snapshot of https://github.com/ent/ent.git (master, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
173
entc/gen/template/builder/create.tmpl
Normal file
173
entc/gen/template/builder/create.tmpl
Normal file
@@ -0,0 +1,173 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Type */}}
|
||||
|
||||
{{ define "create" }}
|
||||
{{ $pkg := base $.Config.Package }}
|
||||
{{ $runtimeRequired := or $.NumHooks $.NumPolicy }}
|
||||
|
||||
{{ template "header" $ }}
|
||||
|
||||
{{ with extend $ "Imports" $.SiblingImports }}
|
||||
{{ template "import" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ $builder := $.CreateName }}
|
||||
{{ $receiver := $.CreateReceiver }}
|
||||
{{ $mutation := print $receiver ".mutation" }}
|
||||
|
||||
// {{ $builder }} is the builder for creating a {{ $.Name }} entity.
|
||||
type {{ $builder }} struct {
|
||||
config
|
||||
mutation *{{ $.MutationName }}
|
||||
hooks []Hook
|
||||
{{- /* Additional fields to add to the builder. */}}
|
||||
{{- $tmpl := printf "dialect/%s/create/fields" $.Storage }}
|
||||
{{- if hasTemplate $tmpl }}
|
||||
{{- xtemplate $tmpl . }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder }}
|
||||
{{ template "setter" . }}
|
||||
{{ end }}
|
||||
|
||||
// Save creates the {{ $.Name }} in the database.
|
||||
func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (*{{ $.Name }}, error) {
|
||||
{{- if $.HasDefault }}
|
||||
{{- if $runtimeRequired }}
|
||||
if err := {{ $receiver }}.defaults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{- else }}
|
||||
{{ $receiver }}.defaults()
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return withHooks(ctx, {{ $receiver }}.{{ $.Storage }}Save, {{ $mutation }}, {{ $receiver }}.hooks)
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func ({{ $receiver }} *{{ $builder }}) SaveX(ctx context.Context) *{{ $.Name }} {
|
||||
v, err := {{ $receiver }}.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func ({{ $receiver }} *{{ $builder }}) Exec(ctx context.Context) error {
|
||||
_, err := {{ $receiver }}.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) ExecX(ctx context.Context) {
|
||||
if err := {{ $receiver }}.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
{{- $fields := $.Fields }}{{ if $.HasOneFieldID }}{{ if $.ID.UserDefined }}{{ $fields = append $fields $.ID }}{{ end }}{{ end }}
|
||||
{{ if $.HasDefault }}
|
||||
// defaults sets the default values of the builder before save.
|
||||
func ({{ $receiver }} *{{ $builder }}) defaults() {{ if $runtimeRequired }}error{{ end }}{
|
||||
{{- range $f := $fields }}
|
||||
{{- if $f.Default }}
|
||||
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {
|
||||
{{- if and $runtimeRequired $f.DefaultFunc }}
|
||||
if {{ $.Package }}.{{ $f.DefaultName }} == nil {
|
||||
return fmt.Errorf("{{ $pkg }}: uninitialized {{ $.Package }}.{{ $f.DefaultName }} (forgotten import {{ $pkg }}/runtime?)")
|
||||
}
|
||||
{{- end }}
|
||||
v := {{ $.Package }}.{{ $f.DefaultName }}{{ if $f.DefaultFunc }}(){{ end }}
|
||||
{{ $mutation }}.{{ $f.MutationSet }}(v)
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $runtimeRequired }}
|
||||
return nil
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func ({{ $receiver }} *{{ $builder }}) check() error {
|
||||
{{- range $f := $fields }}
|
||||
{{- if and $f.IsBlobLazy (not (hasTemplate (printf "dialect/%s/model/fields" $.Storage))) }}{{ continue }}{{ end }}
|
||||
{{- $skip := false }}{{ if $.HasOneFieldID }}{{ if eq $f.Name $.ID.Name }}{{ $skip = true }}{{ end }}{{ end }}
|
||||
{{- if and (not $f.Optional) (not $skip) }}
|
||||
{{- $dialects := $f.RequiredFor }}
|
||||
{{- $n := len $dialects }}
|
||||
{{- if $n }}
|
||||
{{- $partially := ne $n (len $.Config.Storage.Dialects) }}
|
||||
{{- if $partially }}
|
||||
switch {{ $receiver }}.driver.Dialect() {
|
||||
case {{ join $dialects ", " }}:
|
||||
{{- end }}
|
||||
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {
|
||||
return &ValidationError{Name: "{{ $f.Name }}", err: errors.New(`{{ $pkg }}: missing required field "{{ $.Name }}.{{ $f.Name }}"`)}
|
||||
}
|
||||
{{- if $partially }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $isValidator := and ($f.HasGoType) ($f.Type.Validator) }}
|
||||
{{- with or $f.Validators $f.IsEnum $isValidator }}
|
||||
if v, ok := {{ $mutation }}.{{ $f.MutationGet }}(); ok {
|
||||
if err := {{ if or $f.Validators $f.IsEnum }}{{ $.Package }}.{{ $f.Validator }}({{ $f.BasicType "v" }}){{ else }}v.Validate(){{ end }}; err != nil {
|
||||
return &ValidationError{Name: "{{ $f.Name }}", err: fmt.Errorf(`{{ $pkg }}: validator failed for field "{{ $.Name }}.{{ $f.Name }}": %w`, err)}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $e := $.EdgesWithID }}
|
||||
{{- if not $e.Optional }}
|
||||
if len({{ $mutation }}.{{ $e.StructField }}IDs()) == 0 {
|
||||
return &ValidationError{Name: "{{ $e.Name }}", err: errors.New(`{{ $pkg }}: missing required edge "{{ $.Name }}.{{ $e.Name }}"`)}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder }}
|
||||
{{ $tmpl := printf "dialect/%s/create" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{- /* Support adding create methods by global templates. */}}
|
||||
{{- with $tmpls := matchTemplate "create/additional/*" }}
|
||||
{{- range $tmpl := $tmpls }}
|
||||
{{ xtemplate $tmpl $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ $bulk := $.CreateBulkName }}
|
||||
{{ $receiver = $.CreateBulReceiver }}
|
||||
|
||||
// {{ $bulk }} is the builder for creating many {{ $.Name }} entities in bulk.
|
||||
type {{ $bulk }} struct {
|
||||
config
|
||||
err error
|
||||
builders []*{{ $builder }}
|
||||
{{- /* Additional fields to add to the builder. */}}
|
||||
{{- $tmpl = printf "dialect/%s/create_bulk/fields" $.Storage }}
|
||||
{{- if hasTemplate $tmpl }}
|
||||
{{- xtemplate $tmpl . }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{/* If the storage driver supports bulk creation */}}
|
||||
{{ $tmpl = printf "dialect/%s/create_bulk" $.Storage }}
|
||||
{{ if hasTemplate $tmpl }}
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $bulk }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
97
entc/gen/template/builder/delete.tmpl
Normal file
97
entc/gen/template/builder/delete.tmpl
Normal file
@@ -0,0 +1,97 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Type */}}
|
||||
|
||||
{{ define "delete" }}
|
||||
{{ $pkg := base $.Config.Package }}
|
||||
|
||||
{{ template "header" $ }}
|
||||
|
||||
{{ template "import" $ }}
|
||||
|
||||
import (
|
||||
{{ $.PackageAlias }} "{{ $.Config.Package }}/{{ $.PackageDir }}"
|
||||
)
|
||||
|
||||
{{ $builder := $.DeleteName }}
|
||||
{{ $receiver := $.DeleteReceiver }}
|
||||
{{ $mutation := print $receiver ".mutation" }}
|
||||
|
||||
// {{ $builder }} is the builder for deleting a {{ $.Name }} entity.
|
||||
type {{ $builder }} struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *{{ $.MutationName }}
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the {{ $builder }} builder.
|
||||
func ({{ $receiver }} *{{ $builder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $builder }} {
|
||||
{{ $mutation }}.Where(ps...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func ({{ $receiver }} *{{ $builder }}) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, {{ $receiver }}.{{ $.Storage }}Exec, {{ $mutation }}, {{ $receiver }}.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) ExecX(ctx context.Context) int {
|
||||
n, err := {{ $receiver }}.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder }}
|
||||
{{ $tmpl := printf "dialect/%s/delete" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{- /* Support adding delete methods by global templates. */}}
|
||||
{{- with $tmpls := matchTemplate "delete/additional/*" }}
|
||||
{{- range $tmpl := $tmpls }}
|
||||
{{ xtemplate $tmpl $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ $onebuilder := $.DeleteOneName }}
|
||||
{{ $oneReceiver := $.DeleteOneReceiver }}
|
||||
|
||||
// {{ $onebuilder }} is the builder for deleting a single {{ $.Name }} entity.
|
||||
type {{ $onebuilder }} struct {
|
||||
{{ $receiver }} *{{ $builder }}
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the {{ $builder }} builder.
|
||||
func ({{ $oneReceiver }} *{{ $onebuilder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $onebuilder }} {
|
||||
{{ $oneReceiver }}.{{ $mutation }}.Where(ps...)
|
||||
return {{ $oneReceiver }}
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func ({{ $oneReceiver }} *{{ $onebuilder }}) Exec(ctx context.Context) error {
|
||||
n, err := {{ $oneReceiver }}.{{ $receiver }}.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{ {{ $.Package }}.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func ({{ $oneReceiver }} *{{ $onebuilder }}) ExecX(ctx context.Context) {
|
||||
if err := {{ $oneReceiver }}.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
14
entc/gen/template/builder/entql.tmpl
Normal file
14
entc/gen/template/builder/entql.tmpl
Normal file
@@ -0,0 +1,14 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}
|
||||
|
||||
{{ define "entql" }}
|
||||
{{ $tmpl := printf "dialect/%s/entql" $.Storage }}
|
||||
{{ if hasTemplate $tmpl }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
213
entc/gen/template/builder/mutation_graph.tmpl
Normal file
213
entc/gen/template/builder/mutation_graph.tmpl
Normal file
@@ -0,0 +1,213 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}
|
||||
|
||||
{{ define "mutation_graph" }}
|
||||
|
||||
{{ $pkg := base $.Config.Package }}
|
||||
{{ template "header" $ }}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
{{- range $n := $.Nodes }}
|
||||
{{ $n.PackageAlias }} "{{ $.Config.Package }}/{{ $n.PackageDir }}"
|
||||
{{- template "import/types" $n }}
|
||||
{{- end }}
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/schema/field"
|
||||
)
|
||||
|
||||
const (
|
||||
// Operation types.
|
||||
OpCreate = ent.OpCreate
|
||||
OpDelete = ent.OpDelete
|
||||
OpDeleteOne = ent.OpDeleteOne
|
||||
OpUpdate = ent.OpUpdate
|
||||
OpUpdateOne = ent.OpUpdateOne
|
||||
|
||||
// Node types.
|
||||
{{- range $n := $.Nodes }}
|
||||
{{ $n.TypeName }} = "{{ $n.Name }}"
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{ range $n := $.MutableNodes }}
|
||||
|
||||
{{ $mutation := $n.MutationName }}
|
||||
{{ $baseMutation := print $n.Package ".Mutation" }}
|
||||
// {{ $mutation }} represents an operation that mutates the {{ $n.Name }} nodes in the graph.
|
||||
type {{ $mutation }} struct {
|
||||
{{ $baseMutation }}
|
||||
config
|
||||
{{- with $n.HasOneFieldID }}
|
||||
{{ $n.ID.BuilderField }} *{{ $n.ID.Type }}
|
||||
{{- end }}
|
||||
done bool
|
||||
oldValue func(context.Context) (*{{ $n.Name }}, error)
|
||||
}
|
||||
|
||||
var _ ent.Mutation = (*{{ $mutation }})(nil)
|
||||
|
||||
{{ $mutationOption := print (camel $n.Name) "Option" }}
|
||||
// {{ $mutationOption }} allows management of the mutation configuration using functional options.
|
||||
type {{ $mutationOption }} func(*{{ $mutation }})
|
||||
|
||||
// new{{ $mutation }} creates new mutation for the {{ $n.Name }} entity.
|
||||
func new{{ $mutation }}(c config, op Op, opts ...{{ $mutationOption }}) *{{ $mutation }} {
|
||||
m := &{{ $mutation }}{
|
||||
Mutation: *{{ $n.Package }}.NewMutation(op),
|
||||
config: c,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
{{ with $n.HasOneFieldID }}
|
||||
{{ if $n.ID.UserDefined }}
|
||||
// SetID sets the value of the id field. Note that this
|
||||
// operation is only accepted on creation of {{ $n.Name }} entities.
|
||||
func (m *{{ $mutation }}) SetID(id {{ $n.ID.Type }}) {
|
||||
m.{{ $n.ID.BuilderField }} = &id
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// ID returns the ID value in the mutation. Note that the ID is only available
|
||||
// if it was provided to the builder or after it was returned from the database.
|
||||
func (m *{{ $mutation }}) ID() (id {{ $n.ID.Type }}, exists bool) {
|
||||
if m.{{ $n.ID.BuilderField }} == nil {
|
||||
return
|
||||
}
|
||||
return *m.{{ $n.ID.BuilderField }}, true
|
||||
}
|
||||
|
||||
{{ $opt := print "with" $n.Name "ID" }}
|
||||
// {{ $opt }} sets the ID field of the mutation.
|
||||
func {{ $opt }}(id {{ $n.ID.Type }}) {{ $mutationOption }} {
|
||||
return func(m *{{ $mutation }}) {
|
||||
var (
|
||||
err error
|
||||
once sync.Once
|
||||
value *{{ $n.Name }}
|
||||
)
|
||||
m.oldValue = func(ctx context.Context) (*{{ $n.Name }}, error) {
|
||||
once.Do(func() {
|
||||
if m.done {
|
||||
err = errors.New("querying old values post mutation is not allowed")
|
||||
} else {
|
||||
value, err = m.Client().{{ $n.Name }}.Get(ctx, id)
|
||||
}
|
||||
})
|
||||
return value, err
|
||||
}
|
||||
m.{{ $n.ID.BuilderField }} = &id
|
||||
}
|
||||
}
|
||||
|
||||
{{ $opt = print "with" $n.Name }}
|
||||
// {{ $opt }} sets the old {{ $n.Name }} of the mutation.
|
||||
func {{ $opt }}(node *{{ $n.Name }}) {{ $mutationOption }} {
|
||||
return func(m *{{ $mutation }}) {
|
||||
m.oldValue = func(context.Context) (*{{ $n.Name }}, error) {
|
||||
return node, nil
|
||||
}
|
||||
m.{{ $n.ID.BuilderField }} = &node.ID
|
||||
}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// 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 {{ $mutation }}) 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 {{ $mutation }}) Tx() (*Tx, error) {
|
||||
if _, ok := m.driver.(*txDriver); !ok {
|
||||
return nil, errors.New("{{ $pkg }}: mutation is not running in a transaction")
|
||||
}
|
||||
tx := &Tx{config: m.config}
|
||||
tx.init()
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
{{ with $n.HasOneFieldID }}
|
||||
// IDs queries the database and returns the entity ids that match the mutation's predicate.
|
||||
// That means, if the mutation is applied within a transaction with an isolation level such
|
||||
// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
|
||||
// or updated by the mutation.
|
||||
func (m *{{ $mutation }}) IDs(ctx context.Context) ([]{{ $n.ID.Type }}, error) {
|
||||
switch {
|
||||
case m.Op().Is(OpUpdateOne | OpDeleteOne):
|
||||
id, exists := m.ID()
|
||||
if exists {
|
||||
return []{{ $n.ID.Type }}{id}, nil
|
||||
}
|
||||
fallthrough
|
||||
case m.Op().Is(OpUpdate | OpDelete):
|
||||
return m.Client().{{ $n.Name }}.Query().Where(m.Predicates()...).IDs(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("IDs is not allowed on %s operations", m.Op())
|
||||
}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ range $f := $n.Fields }}
|
||||
{{- if $f.IsBlobLazy }}{{ continue }}{{ end }}
|
||||
{{ if $n.HasOneFieldID }}
|
||||
{{ $const := print $n.Package "." $f.Constant }}
|
||||
// {{ $f.MutationGetOld }} returns the old "{{ $f.Name }}" field's value of the {{ $n.Name }} entity.
|
||||
// If the {{ $n.Name }} object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *{{ $mutation }}) {{ $f.MutationGetOld }}(ctx context.Context) (v {{ if $f.NillableValue }}*{{ end }}{{ $f.Type }}, err error) {
|
||||
if !m.Op().Is(OpUpdateOne) {
|
||||
return v, errors.New("{{ $f.MutationGetOld }} is only allowed on UpdateOne operations")
|
||||
}
|
||||
if _, exists := m.ID(); !exists || m.oldValue == nil {
|
||||
return v, errors.New("{{ $f.MutationGetOld }} requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for {{ $f.MutationGetOld }}: %w", err)
|
||||
}
|
||||
return oldValue.{{ $f.StructField }}, nil
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
// 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 *{{ $mutation }}) OldField(ctx context.Context, name string) (ent.Value, error) {
|
||||
{{- if $n.HasCompositeID }}
|
||||
return nil, errors.New("edge schema {{ $n.Name }} does not support getting old values")
|
||||
{{- else }}
|
||||
{{- with $n.Fields }}
|
||||
switch name {
|
||||
{{- range $f := . }}
|
||||
{{- if $f.IsBlobLazy }}{{ continue }}{{ end }}
|
||||
{{- $const := print $n.Package "." $f.Constant }}
|
||||
case {{ $const }}:
|
||||
return m.{{ $f.MutationGetOld }}(ctx)
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
return nil, fmt.Errorf("unknown {{ $n.Name }} field %s", name)
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
500
entc/gen/template/builder/query.tmpl
Normal file
500
entc/gen/template/builder/query.tmpl
Normal file
@@ -0,0 +1,500 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Type */}}
|
||||
|
||||
{{ define "query" }}
|
||||
{{ $pkg := base $.Config.Package }}
|
||||
|
||||
{{ template "header" $ }}
|
||||
|
||||
{{ with extend $ "Imports" $.SiblingImports }}
|
||||
{{ template "import" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ $builder := $.QueryName }}
|
||||
{{ $receiver := $.QueryReceiver }}
|
||||
|
||||
// {{ $builder }} is the builder for querying {{ $.Name }} entities.
|
||||
type {{ $builder }} struct {
|
||||
config
|
||||
ctx *QueryContext
|
||||
order []{{ $.Package }}.OrderOption
|
||||
inters []Interceptor
|
||||
predicates []predicate.{{ $.Name }}
|
||||
{{- /* Eager loading fields. */}}
|
||||
{{- range $e := $.Edges }}
|
||||
{{ $e.EagerLoadField }} *{{ $e.Type.QueryName }}
|
||||
{{- end }}
|
||||
{{- /* Additional fields to add to the builder. */}}
|
||||
{{- $tmpl := printf "dialect/%s/query/fields" $.Storage }}
|
||||
{{- if hasTemplate $tmpl }}
|
||||
{{- xtemplate $tmpl . }}
|
||||
{{- end }}
|
||||
// intermediate query (i.e. traversal path).
|
||||
{{ $.Storage }} {{ $.Storage.Builder }}
|
||||
path func(context.Context) ({{ $.Storage.Builder }}, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the {{ $builder }} builder.
|
||||
func ({{ $receiver }} *{{ $builder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $builder }} {
|
||||
{{ $receiver}}.predicates = append({{ $receiver }}.predicates, ps...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// Limit the number of records to be returned by this query.
|
||||
func ({{ $receiver }} *{{ $builder }}) Limit(limit int) *{{ $builder }} {
|
||||
{{ $receiver }}.ctx.Limit = &limit
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// Offset to start from.
|
||||
func ({{ $receiver }} *{{ $builder }}) Offset(offset int) *{{ $builder }} {
|
||||
{{ $receiver }}.ctx.Offset = &offset
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// 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 ({{ $receiver }} *{{ $builder }}) Unique(unique bool) *{{ $builder }} {
|
||||
{{ $receiver }}.ctx.Unique = &unique
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// Order specifies how the records should be ordered.
|
||||
func ({{ $receiver }} *{{ $builder }}) Order(o ...{{ $.Package }}.OrderOption) *{{ $builder }} {
|
||||
{{ $receiver }}.order = append({{ $receiver }}.order, o...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
{{/* this code has similarity with edge queries in client.tmpl */}}
|
||||
{{ range $e := $.Edges }}
|
||||
{{ $edge_builder := print $e.Type.QueryName }}
|
||||
// Query{{ pascal $e.Name }} chains the current query on the "{{ $e.Name }}" edge.
|
||||
func ({{ $receiver }} *{{ $builder }}) Query{{ pascal $e.Name }}() *{{ $edge_builder }} {
|
||||
query := (&{{ $e.Type.ClientName }}{config: {{ $receiver }}.config}).Query()
|
||||
query.path = func(ctx context.Context) (fromU {{ $.Storage.Builder }}, err error) {
|
||||
if err := {{ $receiver }}.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{- with extend $ "Receiver" $receiver "Edge" $e "Ident" "fromU" -}}
|
||||
{{ $tmpl := printf "dialect/%s/query/path" $.Storage }}
|
||||
{{- xtemplate $tmpl . }}
|
||||
{{- end -}}
|
||||
return fromU, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// First returns the first {{ $.Name }} entity from the query.
|
||||
// Returns a *NotFoundError when no {{ $.Name }} was found.
|
||||
func ({{ $receiver }} *{{ $builder }}) First(ctx context.Context) (*{{ $.Name }}, error) {
|
||||
nodes, err := {{ $receiver }}.Limit(1).All(setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryFirst))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{ {{ $.Package }}.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) FirstX(ctx context.Context) *{{ $.Name }} {
|
||||
node, err := {{ $receiver }}.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
{{ if $.HasOneFieldID }}
|
||||
// FirstID returns the first {{ $.Name }} ID from the query.
|
||||
// Returns a *NotFoundError when no {{ $.Name }} ID was found.
|
||||
func ({{ $receiver }} *{{ $builder }}) FirstID(ctx context.Context) (id {{ $.ID.Type }}, err error) {
|
||||
var ids []{{ $.ID.Type }}
|
||||
if ids, err = {{ $receiver }}.Limit(1).IDs(setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryFirstID)); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{ {{ $.Package }}.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) FirstIDX(ctx context.Context) {{ $.ID.Type }} {
|
||||
id, err := {{ $receiver }}.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// Only returns a single {{ $.Name }} entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one {{ $.Name }} entity is found.
|
||||
// Returns a *NotFoundError when no {{ $.Name }} entities are found.
|
||||
func ({{ $receiver }} *{{ $builder }}) Only(ctx context.Context) (*{{ $.Name }}, error) {
|
||||
nodes, err := {{ $receiver }}.Limit(2).All(setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryOnly))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{ {{ $.Package }}.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{ {{ $.Package }}.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) OnlyX(ctx context.Context) *{{ $.Name }} {
|
||||
node, err := {{ $receiver }}.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
{{ if $.HasOneFieldID }}
|
||||
// OnlyID is like Only, but returns the only {{ $.Name }} ID in the query.
|
||||
// Returns a *NotSingularError when more than one {{ $.Name }} ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func ({{ $receiver }} *{{ $builder }}) OnlyID(ctx context.Context) (id {{ $.ID.Type }}, err error) {
|
||||
var ids []{{ $.ID.Type }}
|
||||
if ids, err = {{ $receiver }}.Limit(2).IDs(setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryOnlyID)); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{ {{ $.Package }}.Label}
|
||||
default:
|
||||
err = &NotSingularError{ {{ $.Package }}.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) OnlyIDX(ctx context.Context) {{ $.ID.Type }} {
|
||||
id, err := {{ $receiver }}.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// All executes the query and returns a list of {{ plural $.Name }}.
|
||||
func ({{ $receiver }} *{{ $builder }}) All(ctx context.Context) ([]*{{ $.Name }}, error) {
|
||||
ctx = setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryAll)
|
||||
if err := {{ $receiver }}.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qr := querierAll[[]*{{ $.Name }}, *{{ $builder }}]()
|
||||
return withInterceptors[[]*{{ $.Name }}](ctx, {{ $receiver }}, qr, {{ $receiver }}.inters)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) AllX(ctx context.Context) []*{{ $.Name }} {
|
||||
nodes, err := {{ $receiver }}.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
{{ if $.HasOneFieldID }}
|
||||
// IDs executes the query and returns a list of {{ $.Name }} IDs.
|
||||
func ({{ $receiver }} *{{ $builder }}) IDs(ctx context.Context) (ids []{{ $.ID.Type }}, err error) {
|
||||
{{- /* Since a graph traversal such as JOINs can return duplicate IDs, set the Unique modifier unless specified otherwise. */}}
|
||||
if {{ $receiver }}.ctx.Unique == nil && {{ $receiver }}.path != nil {
|
||||
{{ $receiver }}.Unique(true)
|
||||
}
|
||||
ctx = setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryIDs)
|
||||
{{- if and $.ID.HasValueScanner (eq $.Storage.Name "sql") }}
|
||||
var nodes []*{{ $.Name }}
|
||||
if nodes, err = {{ $receiver }}.Select({{ $.Package }}.FieldID).All(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ids = make([]{{ $.ID.Type }}, len(nodes))
|
||||
for i := range nodes {
|
||||
ids[i] = nodes[i].ID
|
||||
}
|
||||
{{- else }}
|
||||
if err = {{ $receiver }}.Select({{ $.Package }}.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{- end }}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) IDsX(ctx context.Context) []{{ $.ID.Type }} {
|
||||
ids, err := {{ $receiver }}.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func ({{ $receiver }} *{{ $builder }}) Count(ctx context.Context) (int, error) {
|
||||
ctx = setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryCount)
|
||||
if err := {{ $receiver }}.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return withInterceptors[int](ctx, {{ $receiver }}, querierCount[*{{ $builder }}](), {{ $receiver }}.inters)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) CountX(ctx context.Context) int {
|
||||
count, err := {{ $receiver }}.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func ({{ $receiver }} *{{ $builder }}) Exist(ctx context.Context) (bool, error) {
|
||||
ctx = setContextOp(ctx, {{ $receiver }}.ctx, ent.OpQueryExist)
|
||||
switch _, err := {{ $receiver }}.First{{ if $.HasOneFieldID }}ID{{ end }}(ctx);{
|
||||
case IsNotFound(err):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, fmt.Errorf("{{ $pkg }}: check existence: %w", err)
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) ExistX(ctx context.Context) bool {
|
||||
exist, err := {{ $receiver }}.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the {{ $builder }} builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func ({{ $receiver }} *{{ $builder }}) Clone() *{{ $builder }} {
|
||||
if {{ $receiver }} == nil {
|
||||
return nil
|
||||
}
|
||||
return &{{ $builder }}{
|
||||
config: {{ $receiver }}.config,
|
||||
ctx: {{ $receiver }}.ctx.Clone(),
|
||||
order: append([]{{ $.Package }}.OrderOption{}, {{ $receiver }}.order...),
|
||||
inters: append([]Interceptor{}, {{ $receiver }}.inters...),
|
||||
predicates: append([]predicate.{{ $.Name }}{}, {{ $receiver }}.predicates...),
|
||||
{{- range $e := $.Edges }}
|
||||
{{ $e.EagerLoadField }}: {{ $receiver }}.{{ $e.EagerLoadField }}.Clone(),
|
||||
{{- end }}
|
||||
// clone intermediate query.
|
||||
{{ $.Storage }}: {{ $receiver }}.{{ $.Storage }}.Clone(),
|
||||
path: {{ $receiver }}.path,
|
||||
{{- if $.FeatureEnabled "sql/modifier" }}
|
||||
modifiers: append([]func(*sql.Selector){}, {{ $receiver }}.modifiers...),
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
||||
{{- range $e := $.Edges }}
|
||||
{{ $ebuilder := $e.Type.QueryName }}
|
||||
{{ $func := print "With" $e.StructField }}
|
||||
// {{ $func }} tells the query-builder to eager-load the nodes that are connected to
|
||||
// the "{{ $e.Name }}" edge. The optional arguments are used to configure the query builder of the edge.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}(opts ...func(*{{ $ebuilder }})) *{{ $builder }} {
|
||||
query := (&{{ $e.Type.ClientName }}{config: {{ $receiver }}.config}).Query()
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
{{ $receiver }}.{{ $e.EagerLoadField }} = query
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ $groupBuilder := pascal $.Name | printf "%sGroupBy" }}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: {{ join (keys aggregate) ", " }}.
|
||||
{{- with len $.Fields }}
|
||||
{{- $f := index $.Fields 0 }}
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// {{ $f.StructField }} {{ $f.Type }} `{{ $f.StructTag }}`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.{{ pascal $.Name }}.Query().
|
||||
// GroupBy({{ $.Package }}.{{ $f.Constant }}).
|
||||
// Aggregate({{ $pkg }}.Count()).
|
||||
// Scan(ctx, &v)
|
||||
//
|
||||
{{- end }}
|
||||
func ({{ $receiver }} *{{ $builder }}) GroupBy(field string, fields ...string) *{{ $groupBuilder }} {
|
||||
{{ $receiver }}.ctx.Fields = append([]string{field}, fields...)
|
||||
grbuild := &{{ $groupBuilder }}{build: {{ $receiver }}}
|
||||
grbuild.flds = &{{ $receiver }}.ctx.Fields
|
||||
grbuild.label = {{ $.Package }}.Label
|
||||
grbuild.scan = grbuild.Scan
|
||||
return grbuild
|
||||
}
|
||||
|
||||
{{ $selectBuilder := pascal $.Name | printf "%sSelect" }}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
{{- with len $.Fields }}
|
||||
{{- $f := index $.Fields 0 }}
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// {{ $f.StructField }} {{ $f.Type }} `{{ $f.StructTag }}`
|
||||
// }
|
||||
//
|
||||
// client.{{ pascal $.Name }}.Query().
|
||||
// Select({{ $.Package }}.{{ $f.Constant }}).
|
||||
// Scan(ctx, &v)
|
||||
//
|
||||
{{- end }}
|
||||
func ({{ $receiver }} *{{ $builder }}) Select(fields ...string) *{{ $selectBuilder }} {
|
||||
{{ $receiver }}.ctx.Fields = append({{ $receiver }}.ctx.Fields, fields...)
|
||||
sbuild := &{{ $selectBuilder }}{ {{ $builder }}: {{ $receiver }} }
|
||||
sbuild.label = {{ $.Package }}.Label
|
||||
sbuild.flds, sbuild.scan = &{{ $receiver }}.ctx.Fields, sbuild.Scan
|
||||
return sbuild
|
||||
}
|
||||
|
||||
// Aggregate returns a {{ $selectBuilder }} configured with the given aggregations.
|
||||
func ({{ $receiver }} *{{ $builder }}) Aggregate(fns ...AggregateFunc) *{{ $selectBuilder }} {
|
||||
return {{ $receiver }}.Select().Aggregate(fns...)
|
||||
}
|
||||
|
||||
func ({{ $receiver }} *{{ $builder }}) prepareQuery(ctx context.Context) error {
|
||||
for _, inter := range {{ $receiver }}.inters {
|
||||
if inter == nil {
|
||||
return fmt.Errorf("{{ $pkg }}: uninitialized interceptor (forgotten import {{ $pkg }}/runtime?)")
|
||||
}
|
||||
if trv, ok := inter.(Traverser); ok {
|
||||
if err := trv.Traverse(ctx, {{ $receiver }}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- /* Optional prepare checks per dialect. */}}
|
||||
{{- $tmpl = printf "dialect/%s/query/preparecheck" $.Storage }}
|
||||
{{- if hasTemplate $tmpl }}
|
||||
{{- with extend $ "Receiver" $receiver "Package" $pkg }}
|
||||
{{- xtemplate $tmpl . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
if {{ $receiver }}.path != nil {
|
||||
prev, err := {{ $receiver }}.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{ $receiver }}.{{ $.Storage }} = prev
|
||||
}
|
||||
{{- if $.NumPolicy }}
|
||||
if {{ $.Package }}.Policy == nil {
|
||||
return errors.New("{{ $pkg }}: uninitialized {{ $.Package }}.Policy (forgotten import {{ $pkg }}/runtime?)")
|
||||
}
|
||||
if err := {{ $.Package }}.Policy.EvalQuery(ctx, {{ $receiver }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder "Package" $pkg }}
|
||||
{{ $tmpl := printf "dialect/%s/query" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{- /* Support adding query methods by global templates. In order to generate dialect-specific methods,
|
||||
prefix this template with "dialect/{{ .Storage }}". For example: "dialect/sql/query/additional/*". */}}
|
||||
{{- with $tmpls := matchTemplate "query/additional/*" }}
|
||||
{{- range $tmpl := $tmpls }}
|
||||
{{ xtemplate $tmpl $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/* groupby builder */}}
|
||||
|
||||
{{ $groupReceiver := $.GroupReceiver }}
|
||||
|
||||
// {{ $groupBuilder }} is the group-by builder for {{ $.Name }} entities.
|
||||
type {{ $groupBuilder }} struct {
|
||||
selector
|
||||
build *{{ $builder }}
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func ({{ $groupReceiver }} *{{ $groupBuilder }}) Aggregate(fns ...AggregateFunc) *{{ $groupBuilder }} {
|
||||
{{ $groupReceiver }}.fns = append({{ $groupReceiver }}.fns, fns...)
|
||||
return {{ $groupReceiver }}
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func ({{ $groupReceiver }} *{{ $groupBuilder }}) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, {{ $groupReceiver }}.build.ctx, ent.OpQueryGroupBy)
|
||||
if err := {{ $groupReceiver }}.build.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*{{ $builder }}, *{{ $groupBuilder }}](ctx, {{ $groupReceiver }}.build, {{ $groupReceiver }}, {{ $groupReceiver }}.build.inters, v)
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $groupReceiver "Builder" $groupBuilder }}
|
||||
{{ $tmpl := printf "dialect/%s/group" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{/* select builder */}}
|
||||
|
||||
{{ $selectReceiver := $.SelectReceiver }}
|
||||
|
||||
// {{ $selectBuilder }} is the builder for selecting fields of {{ pascal $.Name }} entities.
|
||||
type {{ $selectBuilder }} struct {
|
||||
*{{ $builder }}
|
||||
selector
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the selector query.
|
||||
func ({{ $selectReceiver }} *{{ $selectBuilder }}) Aggregate(fns ...AggregateFunc) *{{ $selectBuilder }} {
|
||||
{{ $selectReceiver }}.fns = append({{ $selectReceiver }}.fns, fns...)
|
||||
return {{ $selectReceiver }}
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func ({{ $selectReceiver }} *{{ $selectBuilder }}) Scan(ctx context.Context, v any) error {
|
||||
ctx = setContextOp(ctx, {{ $selectReceiver }}.ctx, ent.OpQuerySelect)
|
||||
if err := {{ $selectReceiver }}.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return scanWithInterceptors[*{{ $builder }}, *{{ $selectBuilder }}](ctx, {{ $selectReceiver }}.{{ $.QueryName }}, {{ $selectReceiver }}, {{ $selectReceiver }}.inters, v)
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $selectReceiver "Builder" $selectBuilder }}
|
||||
{{ $tmpl := printf "dialect/%s/select" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
150
entc/gen/template/builder/setter.tmpl
Normal file
150
entc/gen/template/builder/setter.tmpl
Normal file
@@ -0,0 +1,150 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Type */}}
|
||||
|
||||
{{ define "setter" }}
|
||||
{{ $builder := pascal $.Scope.Builder }}
|
||||
{{ $receiver := $.Scope.Receiver }}
|
||||
{{ $fields := $.Fields }}
|
||||
{{ $updater := false }}
|
||||
{{ $creator := true }}
|
||||
{{- if or (hasSuffix $builder "Update") (hasSuffix $builder "UpdateOne") }}
|
||||
{{ $updater = true }}
|
||||
{{ $creator = false }}
|
||||
{{ $fields = $.MutableFields }}
|
||||
{{- else if $.HasCompositeID }}
|
||||
{{- else if $.ID.UserDefined }}
|
||||
{{ $fields = append $fields $.ID }}
|
||||
{{- end }}
|
||||
|
||||
{{ range $f := $fields }}
|
||||
{{- if $f.IsBlobLazy }}{{ continue }}{{ end }}
|
||||
{{- /* Skip all blob fields on multi-row Update (blob key updates require UpdateOne). */}}
|
||||
{{- if and $f.IsBlob $updater (not (hasSuffix $builder "UpdateOne")) }}{{ continue }}{{ end }}
|
||||
{{ $func := print "Set" $f.StructField }}
|
||||
// {{ $func }} sets the "{{ $f.Name }}" field.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}(v {{ $f.Type }}) *{{ $builder }} {
|
||||
{{- /* setting numeric type override previous calls to Add. */}}
|
||||
{{- if and $updater $f.SupportsMutationAdd }}
|
||||
{{ $receiver }}.mutation.{{ $f.MutationReset }}()
|
||||
{{- end }}
|
||||
{{ $receiver }}.mutation.{{ $f.MutationSet }}(v)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
{{/* Avoid generating nillable setters for nillable types. */}}
|
||||
{{ $nillableC := and $creator (or $f.Optional $f.Default) }}
|
||||
{{ $nillableU := and $updater (not $f.UpdateDefault) }}
|
||||
{{ $nillableFunc := print "SetNillable" $f.StructField }}
|
||||
{{ $skipNillable := false }}{{ range $fields }}{{ if and (ne .Name $f.Name) (eq .MutationSet $nillableFunc) }}{{ $skipNillable = true }}{{ break }}{{ end }}{{ end }}
|
||||
{{ if and (not $f.Type.Nillable) (not $skipNillable) (or $nillableC $nillableU) }}
|
||||
// {{ $nillableFunc }} sets the "{{ $f.Name }}" field if the given value is not nil.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $nillableFunc }}(v *{{ $f.Type }}) *{{ $builder }} {
|
||||
if v != nil {
|
||||
{{ $receiver }}.{{ $func }}(*v)
|
||||
}
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if and $updater $f.SupportsMutationAdd }}
|
||||
// {{ $f.MutationAdd }} adds value to the "{{ $f.Name }}" field.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $f.MutationAdd }}(v {{ $f.SignedType }}) *{{ $builder }} {
|
||||
{{ $receiver }}.mutation.{{ $f.MutationAdd }}(v)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if and $updater $f.SupportsMutationAppend }}
|
||||
// {{ $f.MutationAppend }} appends value to the "{{ $f.Name }}" field.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $f.MutationAppend }}(v {{ $f.Type }}) *{{ $builder }} {
|
||||
{{ $receiver }}.mutation.{{ $f.MutationAppend }}(v)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if and $f.Optional $updater }}
|
||||
{{ $func := print "Clear" $f.StructField }}
|
||||
// {{ $func }} clears the value of the "{{ $f.Name }}" field.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}() *{{ $builder }} {
|
||||
{{ $receiver }}.mutation.{{ $func }}()
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{- /* Lazy blob setters only on Create and UpdateOne (blob writes require a single-row context). */}}
|
||||
{{- $updateOne := hasSuffix $builder "UpdateOne" }}
|
||||
{{- if or $creator $updateOne }}
|
||||
{{- if hasTemplate (printf "dialect/%s/model/fields" $.Storage) }}
|
||||
{{- range $f := $.BlobFields }}
|
||||
{{- if not $f.IsBlobLazy }}{{ continue }}{{ end }}
|
||||
{{ $func := print "Set" $f.StructField }}
|
||||
// {{ $func }} sets the "{{ $f.Name }}" field.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}(v io.Reader) *{{ $builder }} {
|
||||
{{ $receiver }}.mutation.Set{{ $f.StructField }}(v)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
{{- if and $f.Optional $updateOne }}
|
||||
{{ $clearFunc := print "Clear" $f.StructField }}
|
||||
// {{ $clearFunc }} clears the value of the "{{ $f.Name }}" field.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $clearFunc }}() *{{ $builder }} {
|
||||
{{ $receiver }}.mutation.{{ $clearFunc }}()
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ range $e := $.EdgesWithID }}
|
||||
{{ if and $updater $e.Immutable }}
|
||||
{{/* Skip to the next one as immutable edges cannot be updated. */}}
|
||||
{{continue}}
|
||||
{{ end }}
|
||||
{{ $op := "add" }}{{ $idsFunc := $e.MutationAdd }}{{ if $e.Unique }}{{ $op = "set" }}{{ $idsFunc = $e.MutationSet }}{{ end }}
|
||||
{{/* Check if this setter was already defined by the field-setters (e.g. edge-field with the same name). */}}
|
||||
{{ $withSetter := not $e.HasFieldSetter }}
|
||||
{{ if $withSetter }}
|
||||
// {{ $idsFunc }} {{ $op }}s the "{{ $e.Name }}" edge to the {{ $e.Type.Name }} entity by ID{{ if not $e.Unique }}s{{ end }}.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $idsFunc }}({{ if $e.Unique }}id{{ else }}ids ...{{ end }} {{ $e.Type.ID.Type }}) *{{ $builder }} {
|
||||
{{ $receiver }}.mutation.{{ $idsFunc }}({{ if $e.Unique }}id{{ else }}ids ...{{ end }})
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ end }}
|
||||
{{ if and $e.Unique $e.Optional $withSetter }}
|
||||
{{ $nillableIDsFunc := print "SetNillable" $e.StructField "ID" }}
|
||||
// {{ $nillableIDsFunc }} sets the "{{ $e.Name }}" edge to the {{ $e.Type.Name }} entity by ID if the given value is not nil.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $nillableIDsFunc }}(id *{{ $e.Type.ID.Type }}) *{{ $builder }} {
|
||||
if id != nil {
|
||||
{{ $receiver}} = {{ $receiver }}.{{ $idsFunc }}(*id)
|
||||
}
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ end }}
|
||||
{{ $func := print (pascal $op) $e.StructField }}
|
||||
// {{ $func }} {{ $op }}s the "{{ $e.Name }}" edge{{if not $e.Unique}}s{{ end }} to the {{ $e.Type.Name }} entity.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}(v {{ if not $e.Unique }}...{{ end }}*{{ $e.Type.Name}}) *{{ $builder }} {
|
||||
{{ if $e.Unique -}}
|
||||
return {{ $receiver }}.{{ $idsFunc }}(v.ID)
|
||||
{{- else -}}
|
||||
ids := make([]{{ $e.Type.ID.Type }}, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return {{ $receiver }}.{{ $idsFunc }}(ids...)
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// Mutation returns the {{ $.MutationName }} object of the builder.
|
||||
func ({{ $receiver }} *{{ $builder }}) Mutation() *{{ $.MutationName }} {
|
||||
return {{ $receiver }}.mutation
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
277
entc/gen/template/builder/update.tmpl
Normal file
277
entc/gen/template/builder/update.tmpl
Normal file
@@ -0,0 +1,277 @@
|
||||
{{/*
|
||||
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.
|
||||
*/}}
|
||||
|
||||
{{/* gotype: entgo.io/ent/entc/gen.Type */}}
|
||||
|
||||
{{ define "update" }}
|
||||
{{ $pkg := base $.Config.Package }}
|
||||
|
||||
{{ template "header" $ }}
|
||||
|
||||
{{ with extend $ "Imports" $.SiblingImports }}
|
||||
{{ template "import" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ $builder := $.UpdateName }}
|
||||
{{ $receiver := $.UpdateReceiver }}
|
||||
{{ $mutation := print $receiver ".mutation" }}
|
||||
{{ $runtimeRequired := or $.NumHooks $.NumPolicy }}
|
||||
|
||||
// {{ $builder }} is the builder for updating {{ $.Name }} entities.
|
||||
type {{ $builder }} struct {
|
||||
config
|
||||
{{- template "update/fields" $ -}}
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the {{ $builder }} builder.
|
||||
func ({{ $receiver}} *{{ $builder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $builder }} {
|
||||
{{ $mutation }}.Where(ps...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder }}
|
||||
{{ template "setter" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder }}
|
||||
{{ template "update/edges" . }}
|
||||
{{ end }}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (int, error) {
|
||||
{{- if $.HasUpdateDefault }}
|
||||
{{- if $runtimeRequired }}
|
||||
if err := {{ $receiver }}.defaults(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
{{- else }}
|
||||
{{ $receiver }}.defaults()
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return withHooks(ctx, {{ $receiver }}.{{ $.Storage }}Save, {{ $mutation }}, {{ $receiver }}.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) SaveX(ctx context.Context) int {
|
||||
affected, err := {{ $receiver }}.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func ({{ $receiver }} *{{ $builder }}) Exec(ctx context.Context) error {
|
||||
_, err := {{ $receiver }}.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $builder }}) ExecX(ctx context.Context) {
|
||||
if err := {{ $receiver }}.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder "Package" $pkg }}
|
||||
{{ template "update/checks" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $builder "Package" $pkg }}
|
||||
{{ $tmpl := printf "dialect/%s/update" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{ $onebuilder := $.UpdateOneName }}
|
||||
{{ $receiver = $.UpdateOneReceiver }}
|
||||
{{ $mutation = print $receiver ".mutation" }}
|
||||
|
||||
// {{ $onebuilder }} is the builder for updating a single {{ $.Name }} entity.
|
||||
type {{ $onebuilder }} struct {
|
||||
config
|
||||
fields []string
|
||||
{{- template "update/fields" $ }}
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $onebuilder }}
|
||||
{{ template "setter" . }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $onebuilder }}
|
||||
{{ template "update/edges" . }}
|
||||
{{ end }}
|
||||
|
||||
// Where appends a list predicates to the {{ $builder }} builder.
|
||||
func ({{ $receiver }} *{{ $onebuilder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $onebuilder }} {
|
||||
{{ $mutation }}.Where(ps...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func ({{ $receiver }} *{{ $onebuilder }}) Select(field string, fields ...string) *{{ $onebuilder }} {
|
||||
{{ $receiver }}.fields = append([]string{field}, fields...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated {{ $.Name }} entity.
|
||||
func ({{ $receiver }} *{{ $onebuilder }} ) Save(ctx context.Context) (*{{ $.Name }}, error) {
|
||||
{{- if $.HasUpdateDefault }}
|
||||
{{- if $runtimeRequired }}
|
||||
if err := {{ $receiver }}.defaults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{- else }}
|
||||
{{ $receiver }}.defaults()
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return withHooks(ctx, {{ $receiver }}.{{ $.Storage }}Save, {{ $mutation }}, {{ $receiver }}.hooks)
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $onebuilder }}) SaveX(ctx context.Context) *{{ $.Name }} {
|
||||
node, err := {{ $receiver }}.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func ({{ $receiver }} *{{ $onebuilder }}) Exec(ctx context.Context) error {
|
||||
_, err := {{ $receiver }}.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func ({{ $receiver }} *{{ $onebuilder }}) ExecX(ctx context.Context) {
|
||||
if err := {{ $receiver }}.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $onebuilder "Package" $pkg }}
|
||||
{{ template "update/checks" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ with extend $ "Receiver" $receiver "Builder" $onebuilder "Package" $pkg }}
|
||||
{{ $tmpl := printf "dialect/%s/update" $.Storage }}
|
||||
{{ xtemplate $tmpl . }}
|
||||
{{ end }}
|
||||
|
||||
{{- /* Support adding update methods by global templates. */}}
|
||||
{{- with $tmpls := matchTemplate "update/additional/*" }}
|
||||
{{- range $tmpl := $tmpls }}
|
||||
{{ xtemplate $tmpl $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{/* shared struct fields between the two updaters */}}
|
||||
{{ define "update/fields"}}
|
||||
hooks []Hook
|
||||
mutation *{{ $.MutationName }}
|
||||
{{- /* Additional fields to add to the builder. */}}
|
||||
{{- $tmpl := printf "dialect/%s/update/fields" $.Storage }}
|
||||
{{- if hasTemplate $tmpl }}
|
||||
{{- xtemplate $tmpl . }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* shared edges removal between the two updaters */}}
|
||||
{{ define "update/edges" }}
|
||||
{{ $builder := pascal .Scope.Builder }}
|
||||
{{ $receiver := .Scope.Receiver }}
|
||||
{{ $mutation := print $receiver ".mutation" }}
|
||||
|
||||
{{ range $e := $.EdgesWithID }}
|
||||
{{ if $e.Immutable }}
|
||||
{{/* Skip to the next one as immutable edges cannot be updated. */}}
|
||||
{{continue}}
|
||||
{{ end }}
|
||||
{{ $func := $e.MutationClear }}
|
||||
// {{ $func }} clears {{ if $e.Unique }}the "{{ $e.Name }}" edge{{ else }}all "{{ $e.Name }}" edges{{ end }} to the {{ $e.Type.Name }} entity.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}() *{{ $builder }} {
|
||||
{{ $mutation }}.{{ $func }}()
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ if not $e.Unique }}
|
||||
{{ $idsFunc := print "Remove" (singular $e.Name | pascal) "IDs" }}
|
||||
// {{ $idsFunc }} removes the "{{ $e.Name }}" edge to {{ $e.Type.Name }} entities by IDs.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $idsFunc }}(ids ...{{ $e.Type.ID.Type }}) *{{ $builder }} {
|
||||
{{ $mutation }}.{{ $idsFunc }}(ids...)
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{ $func := print "Remove" $e.StructField }}
|
||||
// {{ $func }} removes "{{ $e.Name }}" edges to {{ $e.Type.Name }} entities.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}(v ...*{{ $e.Type.Name }}) *{{ $builder }} {
|
||||
ids := make([]{{ $e.Type.ID.Type }}, len(v))
|
||||
for i := range v {
|
||||
ids[i] = v[i].ID
|
||||
}
|
||||
return {{ $receiver }}.{{ $idsFunc }}(ids...)
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* shared template for the 2 update builders */}}
|
||||
{{ define "update/checks" }}
|
||||
{{ $pkg := .Scope.Package }}
|
||||
{{ $receiver := .Scope.Receiver }}
|
||||
{{ $builder := pascal .Scope.Builder }}
|
||||
{{ $mutation := print $receiver ".mutation" }}
|
||||
{{ $runtimeRequired := or $.NumHooks $.NumPolicy }}
|
||||
|
||||
{{ if $.HasUpdateDefault }}
|
||||
// defaults sets the default values of the builder before save.
|
||||
func ({{ $receiver }} *{{ $builder }}) defaults() {{ if $runtimeRequired }}error{{ end }}{
|
||||
{{- range $f := $.Fields }}
|
||||
{{- if $f.UpdateDefault }}
|
||||
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {{ if $f.Optional }} && !{{ $mutation }}.{{ $f.StructField }}Cleared() {{ end }} {
|
||||
{{- if $runtimeRequired }}
|
||||
if {{ $.Package }}.{{ $f.UpdateDefaultName }} == nil {
|
||||
return fmt.Errorf("{{ $pkg }}: uninitialized {{ $.Package }}.{{ $f.UpdateDefaultName }} (forgotten import {{ $pkg }}/runtime?)")
|
||||
}
|
||||
{{- end }}
|
||||
v := {{ $.Package }}.{{ $f.UpdateDefaultName }}()
|
||||
{{ $mutation }}.{{ $f.MutationSet }}(v)
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $runtimeRequired }}
|
||||
return nil
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if $.HasUpdateCheckers }}
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func ({{ $receiver }} *{{ $builder }}) check() error {
|
||||
{{- range $f := $.Fields }}
|
||||
{{- $isValidator := and ($f.HasGoType) ($f.Type.Validator) }}
|
||||
{{- with and (not $f.Immutable) (or $f.Validators $f.IsEnum $isValidator) }}
|
||||
if v, ok := {{ $mutation }}.{{ $f.MutationGet }}(); ok {
|
||||
if err := {{ if or $f.Validators $f.IsEnum }}{{ $.Package }}.{{ $f.Validator }}({{ $f.BasicType "v" }}){{ else }}v.Validate(){{ end }}; err != nil {
|
||||
return &ValidationError{Name: "{{ $f.Name }}", err: fmt.Errorf(`{{ $pkg }}: validator failed for field "{{ $.Name }}.{{ $f.Name }}": %w`, err)}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $e := $.Edges }}
|
||||
{{- if and $e.Unique (not $e.Optional) }}
|
||||
if {{ $mutation }}.{{ $e.StructField }}Cleared() && len({{ $mutation }}.{{ $e.StructField }}IDs()) > 0 {
|
||||
return errors.New(`{{ $pkg }}: clearing a required unique edge "{{ $.Name }}.{{ $e.Name }}"`)
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user