entc/gen: simplify the way to get gen.Field operation

External templates should not deal with storage configuration
This commit is contained in:
Ariel Mashraki
2021-06-27 10:50:25 +03:00
committed by Ariel Mashraki
parent ded20a0e36
commit d3a0b89864
11 changed files with 63 additions and 55 deletions

View File

@@ -26,7 +26,7 @@ var (
// Funcs are the predefined template
// functions used by the codegen.
Funcs = template.FuncMap{
"ops": ops,
"ops": fieldOps,
"add": add,
"append": reflect.Append,
"appends": reflect.AppendSlice,
@@ -73,27 +73,27 @@ var (
acronyms = make(map[string]struct{})
)
// ops returns all operations for given field.
func ops(f *Field) (op []Op) {
// fieldOps returns all predicate operations for a given field.
func fieldOps(f *Field) (ops []Op) {
switch t := f.Type.Type; {
case f.HasGoType() && !f.ConvertedToBasic() && !f.Type.Valuer():
case t == field.TypeJSON:
case t == field.TypeBool:
op = boolOps
ops = boolOps
case t == field.TypeString && strings.ToLower(f.Name) != "id":
op = stringOps
ops = stringOps
if f.HasGoType() && !f.ConvertedToBasic() && f.Type.Valuer() {
op = numericOps
ops = numericOps
}
case t == field.TypeEnum || f.IsEdgeField():
op = enumOps
ops = enumOps
default:
op = numericOps
ops = numericOps
}
if f.Optional {
op = append(op, nillableOps...)
ops = append(ops, nillableOps...)
}
return op
return ops
}
// xrange generates a slice of len n.

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
package gen
// Op is a predicate for the where clause.
// Op represents a predicate operation for schema fields.
type Op int
// List of all builtin predicates.
@@ -26,7 +26,7 @@ const (
HasSuffix // endingWith
)
// Name returns the string representation of an predicate.
// Name returns the string representation of an operator.
func (o Op) Name() string {
if int(o) < len(opText) {
return opText[o]
@@ -34,12 +34,12 @@ func (o Op) Name() string {
return "Unknown"
}
// Variadic reports if the predicate is a variadic function.
// Variadic reports if the operator is a variadic function (takes a varying number of arguments).
func (o Op) Variadic() bool {
return o == In || o == NotIn
}
// Niladic reports if the predicate is a niladic predicate.
// Niladic reports if the operator is niladic (takes no arguments).
func (o Op) Niladic() bool {
return o == IsNil || o == NotNil
}

View File

@@ -15,12 +15,12 @@ import (
"log"
"{{ $.Config.Package }}/migrate"
{{ range $_, $n := $.Nodes }}
{{ range $n := $.Nodes }}
"{{ $n.Config.Package }}/{{ $n.Package }}"
{{- end }}
"entgo.io/ent/dialect"
{{ range $_, $import := $.Storage.Imports -}}
{{ range $import := $.Storage.Imports -}}
"{{ $import }}"
{{ end -}}
)
@@ -90,9 +90,9 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
return &Tx{
ctx: ctx,
config: cfg,
{{ range $_, $n := $.Nodes -}}
{{- range $n := $.Nodes }}
{{ $n.Name }}: New{{ $n.Name }}Client(cfg),
{{ end -}}
{{- end }}
}, nil
}

View File

@@ -18,7 +18,7 @@ func ({{ $receiver }} *{{ $.Name }}) FromResponse(res *gremlin.Response) error {
{{- $scan := print "scan" $receiver }}
var {{ $scan }} struct {
ID {{ $.ID.Type }} `json:"id,omitempty"`
{{ range $_, $f := $.Fields }}
{{ range $f := $.Fields }}
{{- $f.StructField }} {{ if and $f.IsTime (not $f.HasGoType) }}int64{{ else }}{{ if $f.NillableValue }}*{{ end }}{{ $f.Type }}{{ end }} `json:"{{ $f.StorageKey }},omitempty"`
{{ end }}
}
@@ -26,7 +26,7 @@ func ({{ $receiver }} *{{ $.Name }}) FromResponse(res *gremlin.Response) error {
return err
}
{{ $receiver }}.ID = {{ $scan }}.ID
{{ range $_, $f := $.Fields }}
{{ range $f := $.Fields }}
{{- $receiver }}.{{ $f.StructField }} = {{ if and $f.IsTime (not $f.HasGoType) }}time.Unix(0, {{ $scan }}.{{ $f.StructField }}) {{ else }}{{- $scan }}.{{ $f.StructField }}{{ end }}
{{ end -}}
return nil
@@ -46,7 +46,7 @@ func ({{ $receiver }} *{{ $slice }}) FromResponse(res *gremlin.Response) error {
{{- $scan := print "scan" $receiver }}
var {{ $scan }} []struct {
ID {{ $.ID.Type }} `json:"id,omitempty"`
{{ range $_, $f := $.Fields }}
{{ range $f := $.Fields }}
{{- $f.StructField }} {{ if and $f.IsTime (not $f.HasGoType) }}int64{{ else }}{{ if $f.NillableValue }}*{{ end }}{{ $f.Type }}{{ end }} `json:"{{ $f.StorageKey }},omitempty"`
{{ end }}
}
@@ -56,9 +56,9 @@ func ({{ $receiver }} *{{ $slice }}) FromResponse(res *gremlin.Response) error {
for _, v := range {{ $scan }} {
*{{ $receiver }} = append(*{{ $receiver }}, &{{ $.Name }}{
ID: v.ID,
{{ range $_, $f := $.Fields }}
{{- $f.StructField }}: {{- if and $f.IsTime (not $f.HasGoType) }}time.Unix(0, v.{{ $f.StructField }}) {{ else }}v.{{ $f.StructField }}{{ end }},
{{ end -}}
{{- range $f := $.Fields }}
{{ $f.StructField }}: {{- if and $f.IsTime (not $f.HasGoType) }}time.Unix(0, v.{{ $f.StructField }}) {{ else }}v.{{ $f.StructField }}{{ end }},
{{- end }}
})
}
return nil

View File

@@ -54,7 +54,7 @@ in the LICENSE file in the root directory of this source tree.
{{ with $.NumM2M }}
var (
{{- range $_, $e := $.Edges }}
{{- range $e := $.Edges }}
{{- if $e.M2M }}
// {{ $e.PKConstant }} and {{ $e.ColumnConstant }}2 are the table columns denoting the
// primary key for the {{ $e.Name }} relation (M2M).

View File

@@ -22,9 +22,9 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
cfg.driver = &txDriver{tx: tx, drv: c.driver}
return &Tx{
config: cfg,
{{ range $_, $n := $.Nodes -}}
{{- range $n := $.Nodes }}
{{ $n.Name }}: New{{ $n.Name }}Client(cfg),
{{ end -}}
{{- end }}
}, nil
}
{{ end }}

View File

@@ -13,7 +13,7 @@ in the LICENSE file in the root directory of this source tree.
{{ end }}
import (
{{ range $_, $n := $.Nodes }}
{{ range $n := $.Nodes }}
"{{ $.Config.Package }}/{{ $n.Package }}"
{{- end }}
@@ -23,10 +23,10 @@ import (
)
var (
{{- range $_, $t := $.Tables }}
{{- range $t := $.Tables }}
{{- /* find type node in the graph of this table, if exists */}}
{{- $node := index $.Nodes 0 }}
{{- range $_, $n := $.Nodes }}{{ if eq $t.Name $n.Table }}{{ $node = $n }}{{ end }}{{ end }}
{{- range $n := $.Nodes }}{{ if eq $t.Name $n.Table }}{{ $node = $n }}{{ end }}{{ end }}
{{- $columns := pascal $t.Name | printf "%sColumns" }}
// {{ $columns }} holds the columns for the "{{ $t.Name }}" table.
{{ $columns }} = []*schema.Column{
@@ -125,7 +125,7 @@ var (
{{- end }}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
{{- range $_, $t := $.Tables }}
{{- range $t := $.Tables }}
{{ pascal $t.Name | printf "%sTable" }},
{{- end }}
}

View File

@@ -20,10 +20,10 @@ import (
// Tx is a transactional client that is created by calling Client.Tx().
type Tx struct {
config
{{ range $_, $n := $.Nodes -}}
{{- range $n := $.Nodes }}
// {{ $n.Name }} is the client for interacting with the {{ $n.Name }} builders.
{{ $n.Name }} *{{ $n.Name }}Client
{{ end }}
{{- end }}
// lazily loaded.
client *Client
@@ -109,9 +109,9 @@ func (tx *Tx) Client() *Client {
}
func (tx *Tx) init() {
{{ range $_, $n := $.Nodes -}}
{{- range $n := $.Nodes }}
tx.{{ $n.Name }} = New{{ $n.Name }}Client(tx.config)
{{ end -}}
{{- end }}
}
{{/* first node for doc example */}}

View File

@@ -22,7 +22,7 @@ func ID(id {{ $.ID.Type }}) predicate.{{ $.Name }} {
)
}
{{ range $op := ops $.ID }}
{{ range $op := $.ID.Ops }}
{{ $arg := "id" }}{{ if $op.Variadic }}{{ $arg = "ids" }}{{ end }}
{{ $func := printf "ID%s" $op.Name }}
// {{ $func }} applies the {{ $op.Name }} predicate on the ID field.
@@ -61,11 +61,7 @@ func ID(id {{ $.ID.Type }}) predicate.{{ $.Name }} {
{{ end }}
{{ range $f := $.Fields }}
{{ $ops := ops $f }}
{{ with $.Storage.Ops }}
{{ $ops = appends $ops (call $.Storage.Ops $f) }}
{{ end }}
{{ range $op := $ops }}
{{ range $op := $f.Ops }}
{{ $arg := "v" }}{{ if $op.Variadic }}{{ $arg = "vs" }}{{ end }}
{{ $stringOp := eq $op.Name "EqualFold" "Contains" "ContainsFold" "HasPrefix" "HasSuffix" }}
{{ $func := print $f.StructField $op.Name }}

View File

@@ -54,6 +54,7 @@ type (
// Field holds the information of a type field used for the templates.
Field struct {
cfg *Config
def *load.Field
// Name is the name of this field in the database schema.
Name string
@@ -195,6 +196,7 @@ func NewType(c *Config, schema *load.Schema) (*Type, error) {
typ := &Type{
Config: c,
ID: &Field{
cfg: c,
Name: "id",
def: &load.Field{
Name: "id",
@@ -214,6 +216,7 @@ func NewType(c *Config, schema *load.Schema) (*Type, error) {
}
for _, f := range schema.Fields {
tf := &Field{
cfg: c,
def: f,
Name: f.Name,
Type: f.Info,
@@ -1388,6 +1391,15 @@ func (f Field) enums(lf *load.Field) ([]Enum, error) {
return enums, nil
}
// Ops returns all predicate operations of the field.
func (f *Field) Ops() []Op {
ops := fieldOps(f)
if f.Name != "id" && f.cfg != nil && f.cfg.Storage.Ops != nil {
ops = append(ops, f.cfg.Storage.Ops(f)...)
}
return ops
}
// Label returns the Gremlin label name of the edge.
// If the edge is inverse
func (e Edge) Label() string {