mirror of
https://github.com/ent/ent.git
synced 2026-05-24 09:31:56 +03:00
entc/gen: add support for WithNamed<E> feature-flag (#2792)
* entc/gen: struct fields and methods for NamedEdge api * entc/gen: generate WithNamedEdge methods for named-edges * entc/gen: implement eager-loading for named-edges * entc/gen: simplify eager-loading template * entc/gen: drop support for unqiue edges in named-based loading * all: codegen * doc/website: named-edges feature-flag * Update doc/md/eager-load.mdx * Update doc/md/eager-load.mdx
This commit is contained in:
109
entc/gen/template/dialect/sql/feature/namedges.tmpl
Normal file
109
entc/gen/template/dialect/sql/feature/namedges.tmpl
Normal file
@@ -0,0 +1,109 @@
|
||||
{{/*
|
||||
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 */}}
|
||||
|
||||
{{/* Templates used by the "namededges" feature-flag to allow eager-loading edges with dynamic names.. */}}
|
||||
|
||||
{{ define "dialect/sql/model/edges/fields/additional/namedges" }}
|
||||
{{- if $.FeatureEnabled "namedges" }}
|
||||
{{- range $e := $.Edges }}
|
||||
{{- if not $e.Unique }}
|
||||
named{{ $e.StructField }} map[string][]*{{ $e.Type.Name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "dialect/sql/model/additional/namedges" }}
|
||||
{{- if $.FeatureEnabled "namedges" }}
|
||||
{{ $receiver := $.Receiver }}
|
||||
{{- range $e := $.Edges }}
|
||||
{{- if not $e.Unique }}
|
||||
{{ $func := print "Named" $e.StructField }}
|
||||
// {{ $func }} returns the {{ $e.StructField }} named value or an error if the edge was not
|
||||
// loaded in eager-loading with this name.
|
||||
func ({{ $receiver }} *{{ $.Name }}) Named{{ $e.StructField }}(name string) ([]*{{ $e.Type.Name }}, error) {
|
||||
if {{ $receiver }}.Edges.named{{ $e.StructField }} == nil {
|
||||
return nil, &NotLoadedError{edge: name}
|
||||
}
|
||||
nodes, ok := {{ $receiver }}.Edges.named{{ $e.StructField }}[name]
|
||||
if !ok {
|
||||
return nil, &NotLoadedError{edge: name}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func ({{ $receiver }} *{{ $.Name }}) appendNamed{{ $e.StructField }}(name string, edges ...*{{ $e.Type.Name }}) {
|
||||
if {{ $receiver }}.Edges.named{{ $e.StructField }} == nil {
|
||||
{{ $receiver }}.Edges.named{{ $e.StructField }} = make(map[string][]*{{ $e.Type.Name }})
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
{{- /* Prefer empty array over nil to stay consistent with the standard eager-loading API. */}}
|
||||
{{ $receiver }}.Edges.named{{ $e.StructField }}[name] = []*{{ $e.Type.Name }}{}
|
||||
} else {
|
||||
{{ $receiver }}.Edges.named{{ $e.StructField }}[name] = append({{ $receiver }}.Edges.named{{ $e.StructField }}[name], edges...)
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{- define "dialect/sql/query/fields/additional/namedges" }}
|
||||
{{- if $.FeatureEnabled "namedges" }}
|
||||
{{- range $e := $.Edges }}
|
||||
{{- if not $e.Unique }}
|
||||
{{ $e.EagerLoadNamedField }} map[string]*{{ $e.Type.QueryName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "dialect/sql/query/additional/namedges" }}
|
||||
{{- if $.FeatureEnabled "namedges" }}
|
||||
{{ $builder := $.QueryName }}
|
||||
{{ $receiver := receiver $builder }}
|
||||
{{- range $e := $.Edges }}
|
||||
{{- if not $e.Unique }}
|
||||
{{ $ebuilder := $e.Type.QueryName }}
|
||||
{{ $func := print "WithNamed" $e.StructField }}
|
||||
// {{ $func }} tells the query-builder to eager-load the nodes that are connected to the "{{ $e.Name }}"
|
||||
// edge with the given name. The optional arguments are used to configure the query builder of the edge.
|
||||
func ({{ $receiver }} *{{ $builder }}) {{ $func }}(name string, opts ...func(*{{ $ebuilder }})) *{{ $builder }} {
|
||||
query := &{{ $ebuilder }}{config: {{ $receiver }}.config}
|
||||
for _, opt := range opts {
|
||||
opt(query)
|
||||
}
|
||||
if {{ $receiver }}.{{ $e.EagerLoadNamedField }} == nil {
|
||||
{{ $receiver }}.{{ $e.EagerLoadNamedField }} = make(map[string]*{{ $e.Type.QueryName }})
|
||||
}
|
||||
{{ $receiver }}.{{ $e.EagerLoadNamedField }}[name] = query
|
||||
return {{ $receiver }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Process nodes before they are returned and resolve named-edges. */}}
|
||||
{{- define "dialect/sql/query/all/nodes/namedges" }}
|
||||
{{- if $.FeatureEnabled "namedges" }}
|
||||
{{- $builder := pascal $.Scope.Builder }}
|
||||
{{- $receiver := receiver $builder }}
|
||||
{{- range $e := $.Edges }}
|
||||
{{- if not $e.Unique }}
|
||||
for name, query := range {{ $receiver }}.{{ $e.EagerLoadNamedField }} {
|
||||
if err := {{ $receiver }}.load{{ $e.StructField }}(ctx, query, nodes,
|
||||
func(n *{{ $.Name }}) { n.appendNamed{{ $e.StructField }}(name) },
|
||||
func(n *{{ $.Name }}, e *{{ $e.Type.Name }}){ n.appendNamed{{ $e.StructField }}(name, e) }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -76,9 +76,9 @@ func ({{ $receiver }} *{{ $builder }}) sqlAll(ctx context.Context, hooks ...quer
|
||||
}
|
||||
{{- range $e := $.Edges }}
|
||||
if query := {{ $receiver }}.{{ $e.EagerLoadField }}; query != nil {
|
||||
if err := {{ $receiver }}.load{{ $e.StructField }}(ctx, query, nodes, {{ if and (not $e.M2M) (not $e.O2M) }}nil{{ else }}
|
||||
if err := {{ $receiver }}.load{{ $e.StructField }}(ctx, query, nodes, {{ if $e.Unique }}nil{{ else }}
|
||||
func(n *{{ $.Name }}){ n.Edges.{{ $e.StructField }} = []*{{ $e.Type.Name }}{} }{{ end }},
|
||||
func(n *{{ $.Name }}, e *{{ $e.Type.Name }}){ n.Edges.{{ $e.StructField }} = {{ if or $e.OwnFK $e.Unique }}e{{ else }}append(n.Edges.{{ $e.StructField }}, e){{ end }} }); err != nil {
|
||||
func(n *{{ $.Name }}, e *{{ $e.Type.Name }}){ n.Edges.{{ $e.StructField }} = {{ if $e.Unique }}e{{ else }}append(n.Edges.{{ $e.StructField }}, e){{ end }} }); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,7 @@ func ({{ $receiver }} *{{ $builder }}) sqlAll(ctx context.Context, hooks ...quer
|
||||
nodeids[nodes[i].ID] = nodes[i]
|
||||
{{- if $e.O2M }}
|
||||
if init != nil {
|
||||
init(nodes[i])
|
||||
init(nodes[i])
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user