mirror of
https://github.com/ent/ent.git
synced 2026-04-28 05:30:56 +03:00
246 lines
7.1 KiB
Go
246 lines
7.1 KiB
Go
// 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.
|
|
|
|
package edge
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"entgo.io/ent/schema"
|
|
)
|
|
|
|
// A Descriptor for edge configuration.
|
|
type Descriptor struct {
|
|
Tag string // struct tag.
|
|
Type string // edge type.
|
|
Name string // edge name.
|
|
Field string // edge field name (e.g. foreign-key).
|
|
RefName string // ref name; inverse only.
|
|
Ref *Descriptor // edge reference; to/from of the same type.
|
|
Unique bool // unique edge.
|
|
Inverse bool // inverse edge.
|
|
Required bool // required on creation.
|
|
StorageKey *StorageKey // optional storage-key configuration.
|
|
Annotations []schema.Annotation // edge annotations.
|
|
}
|
|
|
|
// To defines an association edge between two vertices.
|
|
func To(name string, t interface{}) *assocBuilder {
|
|
return &assocBuilder{desc: &Descriptor{Name: name, Type: typ(t)}}
|
|
}
|
|
|
|
// From represents a reversed-edge between two vertices that has a back-reference to its source edge.
|
|
func From(name string, t interface{}) *inverseBuilder {
|
|
return &inverseBuilder{desc: &Descriptor{Name: name, Type: typ(t), Inverse: true}}
|
|
}
|
|
|
|
func typ(t interface{}) string {
|
|
if rt := reflect.TypeOf(t); rt.NumIn() > 0 {
|
|
return rt.In(0).Name()
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// assocBuilder is the builder for assoc edges.
|
|
type assocBuilder struct {
|
|
desc *Descriptor
|
|
}
|
|
|
|
// Unique sets the edge type to be unique. Basically, it's limited the ent to be one of the two:
|
|
// one2one or one2many. one2one applied if the inverse-edge is also unique.
|
|
func (b *assocBuilder) Unique() *assocBuilder {
|
|
b.desc.Unique = true
|
|
return b
|
|
}
|
|
|
|
// Required indicates that this edge is a required field on creation.
|
|
// Unlike fields, edges are optional by default.
|
|
func (b *assocBuilder) Required() *assocBuilder {
|
|
b.desc.Required = true
|
|
return b
|
|
}
|
|
|
|
// StructTag sets the struct tag of the assoc edge.
|
|
func (b *assocBuilder) StructTag(s string) *assocBuilder {
|
|
b.desc.Tag = s
|
|
return b
|
|
}
|
|
|
|
// From creates an inverse-edge with the same type.
|
|
func (b *assocBuilder) From(name string) *inverseBuilder {
|
|
return &inverseBuilder{desc: &Descriptor{Name: name, Type: b.desc.Type, Inverse: true, Ref: b.desc}}
|
|
}
|
|
|
|
// Field is used to bind an edge (with a foreign-key) to a field in the schema.
|
|
//
|
|
// field.Int("owner_id").
|
|
// Optional()
|
|
//
|
|
// edge.To("owner", User.Type).
|
|
// Field("owner_id").
|
|
// Unique(),
|
|
//
|
|
func (b *assocBuilder) Field(f string) *assocBuilder {
|
|
b.desc.Field = f
|
|
return b
|
|
}
|
|
|
|
// Comment used to put annotations on the schema.
|
|
func (b *assocBuilder) Comment(string) *assocBuilder {
|
|
return b
|
|
}
|
|
|
|
// StorageKey sets the storage key of the edge.
|
|
//
|
|
// edge.To("groups", Group.Type).
|
|
// StorageKey(edge.Table("user_groups"), edge.Columns("user_id", "group_id"))
|
|
//
|
|
func (b *assocBuilder) StorageKey(opts ...StorageOption) *assocBuilder {
|
|
if b.desc.StorageKey == nil {
|
|
b.desc.StorageKey = &StorageKey{}
|
|
}
|
|
for i := range opts {
|
|
opts[i](b.desc.StorageKey)
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Annotations adds a list of annotations to the edge object to be used by
|
|
// codegen extensions.
|
|
//
|
|
// edge.To("pets", Pet.Type).
|
|
// Annotations(entgql.Bind())
|
|
//
|
|
func (b *assocBuilder) Annotations(annotations ...schema.Annotation) *assocBuilder {
|
|
b.desc.Annotations = append(b.desc.Annotations, annotations...)
|
|
return b
|
|
}
|
|
|
|
// Descriptor implements the ent.Descriptor interface.
|
|
func (b *assocBuilder) Descriptor() *Descriptor {
|
|
return b.desc
|
|
}
|
|
|
|
// inverseBuilder is the builder for inverse edges.
|
|
type inverseBuilder struct {
|
|
desc *Descriptor
|
|
}
|
|
|
|
// Ref sets the referenced-edge of this inverse edge.
|
|
func (b *inverseBuilder) Ref(ref string) *inverseBuilder {
|
|
b.desc.RefName = ref
|
|
return b
|
|
}
|
|
|
|
// Unique sets the edge type to be unique. Basically, it's limited the ent to be one of the two:
|
|
// one2one or one2many. one2one applied if the inverse-edge is also unique.
|
|
func (b *inverseBuilder) Unique() *inverseBuilder {
|
|
b.desc.Unique = true
|
|
return b
|
|
}
|
|
|
|
// Required indicates that this edge is a required field on creation.
|
|
// Unlike fields, edges are optional by default.
|
|
func (b *inverseBuilder) Required() *inverseBuilder {
|
|
b.desc.Required = true
|
|
return b
|
|
}
|
|
|
|
// StructTag sets the struct tag of the inverse edge.
|
|
func (b *inverseBuilder) StructTag(s string) *inverseBuilder {
|
|
b.desc.Tag = s
|
|
return b
|
|
}
|
|
|
|
// Comment used to put annotations on the schema.
|
|
func (b *inverseBuilder) Comment(string) *inverseBuilder {
|
|
return b
|
|
}
|
|
|
|
// Field is used to bind an edge (with a foreign-key) to a field in the schema.
|
|
//
|
|
// field.Int("owner_id").
|
|
// Optional()
|
|
//
|
|
// edge.From("owner", User.Type).
|
|
// Ref("pets").
|
|
// Field("owner_id").
|
|
// Unique(),
|
|
//
|
|
func (b *inverseBuilder) Field(f string) *inverseBuilder {
|
|
b.desc.Field = f
|
|
return b
|
|
}
|
|
|
|
// Annotations adds a list of annotations to the edge object to be used by
|
|
// codegen extensions.
|
|
//
|
|
// edge.From("owner", User.Type).
|
|
// Ref("pets").
|
|
// Unique().
|
|
// Annotations(entgql.Bind())
|
|
//
|
|
func (b *inverseBuilder) Annotations(annotations ...schema.Annotation) *inverseBuilder {
|
|
b.desc.Annotations = append(b.desc.Annotations, annotations...)
|
|
return b
|
|
}
|
|
|
|
// Descriptor implements the ent.Descriptor interface.
|
|
func (b *inverseBuilder) Descriptor() *Descriptor {
|
|
return b.desc
|
|
}
|
|
|
|
// StorageKey holds the configuration for edge storage-key.
|
|
type StorageKey struct {
|
|
Table string // Table or label.
|
|
Symbols []string // Symbols/names of the foreign-key constraints.
|
|
Columns []string // Foreign-key columns.
|
|
}
|
|
|
|
// StorageOption allows for setting the storage configuration using functional options.
|
|
type StorageOption func(*StorageKey)
|
|
|
|
// Table sets the table name option for M2M edges.
|
|
func Table(name string) StorageOption {
|
|
return func(key *StorageKey) {
|
|
key.Table = name
|
|
}
|
|
}
|
|
|
|
// Symbol sets the symbol/name of the foreign-key constraint for O2O, O2M and M2O edges.
|
|
// Note that, for M2M edges (2 columns and 2 constraints), use the edge.Symbols option.
|
|
func Symbol(symbol string) StorageOption {
|
|
return func(key *StorageKey) {
|
|
key.Symbols = []string{symbol}
|
|
}
|
|
}
|
|
|
|
// Symbols sets the symbol/name of the foreign-key constraints for M2M edges.
|
|
// The 1st column defines the name of the "To" edge, and the 2nd defines
|
|
// the name of the "From" edge (inverse edge).
|
|
// Note that, for O2O, O2M and M2O edges, use the edge.Symbol option.
|
|
func Symbols(to, from string) StorageOption {
|
|
return func(key *StorageKey) {
|
|
key.Symbols = []string{to, from}
|
|
}
|
|
}
|
|
|
|
// Column sets the foreign-key column name option for O2O, O2M and M2O edges.
|
|
// Note that, for M2M edges (2 columns), use the edge.Columns option.
|
|
func Column(name string) StorageOption {
|
|
return func(key *StorageKey) {
|
|
key.Columns = []string{name}
|
|
}
|
|
}
|
|
|
|
// Columns sets the foreign-key column names option for M2M edges.
|
|
// The 1st column defines the name of the "To" edge, and the 2nd defines
|
|
// the name of the "From" edge (inverse edge).
|
|
// Note that, for O2O, O2M and M2O edges, use the edge.Column option.
|
|
func Columns(to, from string) StorageOption {
|
|
return func(key *StorageKey) {
|
|
key.Columns = []string{to, from}
|
|
}
|
|
}
|