mirror of
https://github.com/ent/ent.git
synced 2026-05-24 09:31:56 +03:00
schema/edge: add annotation support for edges (#651)
This commit is contained in:
@@ -63,11 +63,11 @@ type (
|
||||
func NewGraph(c *Config, schemas ...*load.Schema) (g *Graph, err error) {
|
||||
defer catch(&err)
|
||||
g = &Graph{c, make([]*Type, 0, len(schemas)), schemas}
|
||||
for _, schema := range schemas {
|
||||
g.addNode(schema)
|
||||
for i := range schemas {
|
||||
g.addNode(schemas[i])
|
||||
}
|
||||
for _, schema := range schemas {
|
||||
g.addEdges(schema)
|
||||
for i := range schemas {
|
||||
g.addEdges(schemas[i])
|
||||
}
|
||||
for _, t := range g.Nodes {
|
||||
check(resolve(t), "resolve %q relations", t.Name)
|
||||
@@ -75,8 +75,8 @@ func NewGraph(c *Config, schemas ...*load.Schema) (g *Graph, err error) {
|
||||
for _, t := range g.Nodes {
|
||||
check(t.resolveFKs(), "set %q foreign-keys", t.Name)
|
||||
}
|
||||
for _, schema := range schemas {
|
||||
g.addIndexes(schema)
|
||||
for i := range schemas {
|
||||
g.addIndexes(schemas[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -144,26 +144,28 @@ func (g *Graph) addEdges(schema *load.Schema) {
|
||||
// Assoc only.
|
||||
case !e.Inverse:
|
||||
t.Edges = append(t.Edges, &Edge{
|
||||
def: e,
|
||||
Type: typ,
|
||||
Name: e.Name,
|
||||
Owner: t,
|
||||
Unique: e.Unique,
|
||||
Optional: !e.Required,
|
||||
StructTag: e.Tag,
|
||||
def: e,
|
||||
Type: typ,
|
||||
Name: e.Name,
|
||||
Owner: t,
|
||||
Unique: e.Unique,
|
||||
Optional: !e.Required,
|
||||
StructTag: e.Tag,
|
||||
Annotations: e.Annotations,
|
||||
})
|
||||
// Inverse only.
|
||||
case e.Inverse && e.Ref == nil:
|
||||
expect(e.RefName != "", "missing reference name for inverse edge: %s.%s", t.Name, e.Name)
|
||||
t.Edges = append(t.Edges, &Edge{
|
||||
def: e,
|
||||
Type: typ,
|
||||
Name: e.Name,
|
||||
Owner: typ,
|
||||
Inverse: e.RefName,
|
||||
Unique: e.Unique,
|
||||
Optional: !e.Required,
|
||||
StructTag: e.Tag,
|
||||
def: e,
|
||||
Type: typ,
|
||||
Name: e.Name,
|
||||
Owner: typ,
|
||||
Inverse: e.RefName,
|
||||
Unique: e.Unique,
|
||||
Optional: !e.Required,
|
||||
StructTag: e.Tag,
|
||||
Annotations: e.Annotations,
|
||||
})
|
||||
// Inverse and assoc.
|
||||
case e.Inverse:
|
||||
@@ -171,22 +173,24 @@ func (g *Graph) addEdges(schema *load.Schema) {
|
||||
expect(e.RefName == "", "reference name is derived from the assoc name: %s.%s <-> %s.%s", t.Name, ref.Name, t.Name, e.Name)
|
||||
expect(ref.Type == t.Name, "assoc-inverse edge allowed only as o2o relation of the same type")
|
||||
t.Edges = append(t.Edges, &Edge{
|
||||
def: e,
|
||||
Type: typ,
|
||||
Name: e.Name,
|
||||
Owner: t,
|
||||
Inverse: ref.Name,
|
||||
Unique: e.Unique,
|
||||
Optional: !e.Required,
|
||||
StructTag: e.Tag,
|
||||
def: e,
|
||||
Type: typ,
|
||||
Name: e.Name,
|
||||
Owner: t,
|
||||
Inverse: ref.Name,
|
||||
Unique: e.Unique,
|
||||
Optional: !e.Required,
|
||||
StructTag: e.Tag,
|
||||
Annotations: e.Annotations,
|
||||
}, &Edge{
|
||||
def: e,
|
||||
Type: typ,
|
||||
Owner: t,
|
||||
Name: ref.Name,
|
||||
Unique: ref.Unique,
|
||||
Optional: !ref.Required,
|
||||
StructTag: ref.Tag,
|
||||
def: e,
|
||||
Type: typ,
|
||||
Owner: t,
|
||||
Name: ref.Name,
|
||||
Unique: ref.Unique,
|
||||
Optional: !ref.Required,
|
||||
StructTag: ref.Tag,
|
||||
Annotations: e.Annotations,
|
||||
})
|
||||
default:
|
||||
panic(graphError{"edge must be either an assoc or inverse edge"})
|
||||
|
||||
@@ -77,8 +77,8 @@ type (
|
||||
// UserDefined indicates that this field was defined by the loaded schema.
|
||||
// Unlike default id field, which is defined by the generator.
|
||||
UserDefined bool
|
||||
// Annotations that were defined in the field schema.
|
||||
// The mapping is from the Annotation.Name() to the decoded object.
|
||||
// Annotations that were defined for the field in the schema.
|
||||
// The mapping is from the Annotation.Name() to a JSON decoded object.
|
||||
Annotations map[string]interface{}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,9 @@ type (
|
||||
// edge.To("spouse", User.Type).Unique() // one 2 one.
|
||||
//
|
||||
Bidi bool
|
||||
// Annotations that were defined for the edge in the schema.
|
||||
// The mapping is from the Annotation.Name() to a JSON decoded object.
|
||||
Annotations map[string]interface{}
|
||||
}
|
||||
|
||||
// Relation holds the relational database information for edges.
|
||||
|
||||
@@ -10,4 +10,5 @@ package ent
|
||||
type CardExtension struct {
|
||||
Number string
|
||||
Name string
|
||||
Spec int
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ func (Card) Edges() []ent.Edge {
|
||||
Ref("card").
|
||||
Unique(),
|
||||
edge.From("spec", Spec.Type).
|
||||
Ref("card"),
|
||||
Ref("card").
|
||||
Annotations(&template.Extension{
|
||||
Type: "int",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ in the LICENSE file in the root directory of this source tree.
|
||||
{{ range $n := $.Nodes }}
|
||||
{{ $hasExt := false }}
|
||||
{{ range $f := $n.Fields }}{{ if $f.Annotations.Extension }}{{ $hasExt = true }}{{ end }}{{ end }}
|
||||
{{ range $e := $n.Edges }}{{ if $e.Annotations.Extension }}{{ $hasExt = true }}{{ end }}{{ end }}
|
||||
{{/* If one or fields contain the "Extension" annotation */}}
|
||||
{{ if $hasExt }}
|
||||
// {{ $n.Name }}Extension is a type for holding the extension information defined in the schema.
|
||||
@@ -20,6 +21,11 @@ in the LICENSE file in the root directory of this source tree.
|
||||
{{ $f.StructField }} {{ $ant.Type }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $e := $n.Edges }}
|
||||
{{- with $ant := $e.Annotations.Extension }}
|
||||
{{ $e.StructField }} {{ $ant.Type }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -10,4 +10,5 @@ package ent
|
||||
type CardExtension struct {
|
||||
Number string
|
||||
Name string
|
||||
Spec int
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -57,15 +57,16 @@ type Field struct {
|
||||
|
||||
// Edge represents an ent.Edge that was loaded from a complied user package.
|
||||
type Edge struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
RefName string `json:"ref_name,omitempty"`
|
||||
Ref *Edge `json:"ref,omitempty"`
|
||||
Unique bool `json:"unique,omitempty"`
|
||||
Inverse bool `json:"inverse,omitempty"`
|
||||
Required bool `json:"required,omitempty"`
|
||||
StorageKey *edge.StorageKey `json:"storage_key,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
RefName string `json:"ref_name,omitempty"`
|
||||
Ref *Edge `json:"ref,omitempty"`
|
||||
Unique bool `json:"unique,omitempty"`
|
||||
Inverse bool `json:"inverse,omitempty"`
|
||||
Required bool `json:"required,omitempty"`
|
||||
StorageKey *edge.StorageKey `json:"storage_key,omitempty"`
|
||||
Annotations map[string]interface{} `json:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// Index represents an ent.Index that was loaded from a complied user package.
|
||||
@@ -79,14 +80,18 @@ type Index struct {
|
||||
// NewEdge creates an loaded edge from edge descriptor.
|
||||
func NewEdge(ed *edge.Descriptor) *Edge {
|
||||
ne := &Edge{
|
||||
Tag: ed.Tag,
|
||||
Type: ed.Type,
|
||||
Name: ed.Name,
|
||||
Unique: ed.Unique,
|
||||
Inverse: ed.Inverse,
|
||||
Required: ed.Required,
|
||||
RefName: ed.RefName,
|
||||
StorageKey: ed.StorageKey,
|
||||
Tag: ed.Tag,
|
||||
Type: ed.Type,
|
||||
Name: ed.Name,
|
||||
Unique: ed.Unique,
|
||||
Inverse: ed.Inverse,
|
||||
Required: ed.Required,
|
||||
RefName: ed.RefName,
|
||||
StorageKey: ed.StorageKey,
|
||||
Annotations: make(map[string]interface{}),
|
||||
}
|
||||
for _, at := range ed.Annotations {
|
||||
ne.Annotations[at.Name()] = at
|
||||
}
|
||||
if ref := ed.Ref; ref != nil {
|
||||
ne.Ref = NewEdge(ref)
|
||||
|
||||
@@ -60,7 +60,8 @@ func (User) Fields() []ent.Field {
|
||||
|
||||
func (User) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.To("groups", Group.Type),
|
||||
edge.To("groups", Group.Type).
|
||||
Annotations(&OrderConfig{FieldName: "name"}),
|
||||
edge.To("parent", User.Type).
|
||||
Unique().
|
||||
StorageKey(edge.Column("user_parent_id")).
|
||||
@@ -139,6 +140,10 @@ func TestMarshalSchema(t *testing.T) {
|
||||
require.Equal(t, "groups", schema.Edges[0].Name)
|
||||
require.Equal(t, "Group", schema.Edges[0].Type)
|
||||
require.False(t, schema.Edges[0].Inverse)
|
||||
require.NotEmpty(t, schema.Edges[0].Annotations)
|
||||
ant = schema.Edges[0].Annotations["order_config"].(map[string]interface{})
|
||||
require.Equal(t, ant["FieldName"], "name")
|
||||
|
||||
require.Equal(t, "children", schema.Edges[1].Name)
|
||||
require.Equal(t, "user_parent_id", schema.Edges[1].StorageKey.Columns[0])
|
||||
require.Equal(t, "User", schema.Edges[1].Type)
|
||||
|
||||
Reference in New Issue
Block a user