From 307eb5e30bfbbd27efabab1e89ffe41116881a18 Mon Sep 17 00:00:00 2001
From: Ariel Mashraki <7413593+a8m@users.noreply.github.com>
Date: Mon, 23 Jan 2023 15:53:33 +0200
Subject: [PATCH] doc/edges: add erds to examples (#3268)
---
doc/md/schema-edges.mdx | 197 ++++++++++++++++++++++--
examples/o2mrecur/ent/migrate/schema.go | 2 +-
examples/o2mrecur/ent/mutation.go | 90 +++++++++--
examples/o2mrecur/ent/node.go | 19 +--
examples/o2mrecur/ent/node/node.go | 18 +--
examples/o2mrecur/ent/node/where.go | 35 +++++
examples/o2mrecur/ent/node_create.go | 16 +-
examples/o2mrecur/ent/node_query.go | 25 +--
examples/o2mrecur/ent/node_update.go | 40 +++--
examples/o2mrecur/ent/schema/node.go | 3 +
examples/o2mrecur/example_test.go | 4 +-
examples/o2orecur/ent/migrate/schema.go | 2 +-
examples/o2orecur/ent/mutation.go | 90 +++++++++--
examples/o2orecur/ent/node.go | 19 +--
examples/o2orecur/ent/node/node.go | 18 +--
examples/o2orecur/ent/node/where.go | 35 +++++
examples/o2orecur/ent/node_create.go | 16 +-
examples/o2orecur/ent/node_query.go | 25 +--
examples/o2orecur/ent/node_update.go | 40 +++--
examples/o2orecur/ent/schema/node.go | 3 +
20 files changed, 527 insertions(+), 170 deletions(-)
diff --git a/doc/md/schema-edges.mdx b/doc/md/schema-edges.mdx
index fc0d85bfc..e18da490c 100644
--- a/doc/md/schema-edges.mdx
+++ b/doc/md/schema-edges.mdx
@@ -8,16 +8,33 @@ import TabItem from '@theme/TabItem';
## Quick Summary
-Edges are the relations (or associations) of entities. For example, user's pets, or group's users.
+Edges are the relations (or associations) of entities. For example, user's pets, or group's users:
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/38be6c19)
+
+
+
+
+
+
In the example above, you can see 2 relations declared using edges. Let's go over them.
-1\. `pets` / `owner` edges; user's pets and pet's owner -
+1\. `pets` / `owner` edges; user's pets and pet's owner:
-```go title="ent/schema/user.go"
+
+
+
+```go title="ent/schema/user.go" {23}
package schema
import (
@@ -44,8 +61,10 @@ func (User) Edges() []ent.Edge {
}
}
```
+
+
-```go title="ent/schema/pet.go"
+```go title="ent/schema/pet.go" {23-25}
package schema
import (
@@ -74,6 +93,8 @@ func (Pet) Edges() []ent.Edge {
}
}
```
+
+
As you can see, a `User` entity can **have many** pets, but a `Pet` entity can **have only one** owner.
In relationship definition, the `pets` edge is a *O2M* (one-to-many) relationship, and the `owner` edge
@@ -88,9 +109,12 @@ references from one schema to other.
The cardinality of the edge/relationship can be controlled using the `Unique` method, and it's explained
more widely below.
-2\. `users` / `groups` edges; group's users and user's groups -
+2\. `users` / `groups` edges; group's users and user's groups:
-```go title="ent/schema/group.go"
+
+
+
+```go title="ent/schema/group.go" {23}
package schema
import (
@@ -117,8 +141,10 @@ func (Group) Edges() []ent.Edge {
}
}
```
+
+
-```go title="ent/schema/user.go"
+```go title="ent/schema/user.go" {23-24}
package schema
import (
@@ -148,6 +174,8 @@ func (User) Edges() []ent.Edge {
}
}
```
+
+
As you can see, a Group entity can **have many** users, and a User entity can have **have many** groups.
In relationship definition, the `users` edge is a *M2M* (many-to-many) relationship, and the `groups`
@@ -175,13 +203,31 @@ Let's go over a few examples that show how to define different relation types us
## O2O Two Types
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/b6264668)
+
+
+
+
+
+
In this example, a user **has only one** credit-card, and a card **has only one** owner.
The `User` schema defines an `edge.To` card named `card`, and the `Card` schema
defines a back-reference to this edge using `edge.From` named `owner`.
+
+
+
```go title="ent/schema/user.go"
// Edges of the user.
func (User) Edges() []ent.Edge {
@@ -191,6 +237,8 @@ func (User) Edges() []ent.Edge {
}
}
```
+
+
```go title="ent/schema/card.go"
// Edges of the Card.
@@ -206,6 +254,8 @@ func (Card) Edges() []ent.Edge {
}
}
```
+
+
The API for interacting with these edges is as follows:
```go
@@ -251,8 +301,23 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## O2O Same Type
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/6645164b)
+
+
+
+
+
+
In this linked-list example, we have a **recursive relation** named `next`/`prev`. Each node in the list can
**have only one** `next` node. If a node A points (using `next`) to node B, B can get its pointer using `prev` (the back-reference edge).
@@ -346,8 +411,23 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## O2O Bidirectional
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/e2e76d55)
+
+
+
+
+
+
In this user-spouse example, we have a **symmetric O2O relation** named `spouse`. Each user can **have only one** spouse.
If user A sets its spouse (using `spouse`) to B, B can get its spouse using the `spouse` edge.
@@ -441,15 +521,33 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## O2M Two Types
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/8a360fce)
+
+
+
+
+
+
In this user-pets example, we have a O2M relation between user and its pets.
Each user **has many** pets, and a pet **has one** owner.
If user A adds a pet B using the `pets` edge, B can get its owner using the `owner` edge (the back-reference edge).
Note that this relation is also a M2O (many-to-one) from the point of view of the `Pet` schema.
-```go title="ent/schema/user.go"
+
+
+
+```go title="ent/schema/user.go" {4}
// Edges of the User.
func (User) Edges() []ent.Edge {
return []ent.Edge{
@@ -457,8 +555,10 @@ func (User) Edges() []ent.Edge {
}
}
```
+
+
-```go title="ent/schema/pet.go"
+```go title="ent/schema/pet.go" {4-6}
// Edges of the Pet.
func (Pet) Edges() []ent.Edge {
return []ent.Edge{
@@ -468,6 +568,8 @@ func (Pet) Edges() []ent.Edge {
}
}
```
+
+
The API for interacting with these edges is as follows:
@@ -520,7 +622,7 @@ func Do(ctx context.Context, client *ent.Client) error {
Note that, the foreign-key column can be configured and exposed as an entity field using the
[Edge Field](#edge-field) option as follows:
-```go {4,15}
+```go title="ent/schema/pet.go" {4,15}
// Fields of the Pet.
func (Pet) Fields() []ent.Field {
return []ent.Field{
@@ -544,8 +646,23 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## O2M Same Type
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/74c74ac7)
+
+
+
+
+
+
In this example, we have a recursive O2M relation between tree's nodes and their children (or their parent).
Each node in the tree **has many** children, and **has one** parent. If node A adds B to its children,
B can get its owner using the `owner` edge.
@@ -674,8 +791,23 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## M2M Two Types
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/25b70c29)
+
+
+
+
+
+
In this groups-users example, we have a M2M relation between groups and their users.
Each group **has many** users, and each user can be joined to **many** groups.
@@ -780,8 +912,23 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## M2M Same Type
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/8cb4fd4e)
+
+
+
+
+
+
In this following-followers example, we have a M2M relation between users to their followers. Each user
can follow **many** users, and can have **many** followers.
@@ -888,8 +1035,23 @@ The full example exists in [GitHub](https://github.com/ent/ent/tree/master/examp
## M2M Bidirectional
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/74c5bd30)
+
+
+
+
+
+
In this user-friends example, we have a **symmetric M2M relation** named `friends`.
Each user can **have many** friends. If user A becomes a friend of B, B is also a friend of A.
@@ -1058,8 +1220,23 @@ In the following example, we demonstrate how to model the friendship between two
required fields of the relationship (`user_id` and `friend_id`), and an additional field named `created_at` whose value
is automatically set on creation.
+
+
+

+
+
+
+[](https://gh.atlasgo.cloud/explore/90e2415f)
+
+
+
+
+
+
0 {
diff --git a/examples/o2mrecur/ent/node_query.go b/examples/o2mrecur/ent/node_query.go
index c7f2d883f..2d134b085 100644
--- a/examples/o2mrecur/ent/node_query.go
+++ b/examples/o2mrecur/ent/node_query.go
@@ -28,7 +28,6 @@ type NodeQuery struct {
predicates []predicate.Node
withParent *NodeQuery
withChildren *NodeQuery
- withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@@ -406,19 +405,12 @@ func (nq *NodeQuery) prepareQuery(ctx context.Context) error {
func (nq *NodeQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Node, error) {
var (
nodes = []*Node{}
- withFKs = nq.withFKs
_spec = nq.querySpec()
loadedTypes = [2]bool{
nq.withParent != nil,
nq.withChildren != nil,
}
)
- if nq.withParent != nil {
- withFKs = true
- }
- if withFKs {
- _spec.Node.Columns = append(_spec.Node.Columns, node.ForeignKeys...)
- }
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*Node).scanValues(nil, columns)
}
@@ -457,10 +449,7 @@ func (nq *NodeQuery) loadParent(ctx context.Context, query *NodeQuery, nodes []*
ids := make([]int, 0, len(nodes))
nodeids := make(map[int][]*Node)
for i := range nodes {
- if nodes[i].node_children == nil {
- continue
- }
- fk := *nodes[i].node_children
+ fk := nodes[i].ParentID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
@@ -477,7 +466,7 @@ func (nq *NodeQuery) loadParent(ctx context.Context, query *NodeQuery, nodes []*
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
- return fmt.Errorf(`unexpected foreign-key "node_children" returned %v`, n.ID)
+ return fmt.Errorf(`unexpected foreign-key "parent_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
@@ -495,7 +484,6 @@ func (nq *NodeQuery) loadChildren(ctx context.Context, query *NodeQuery, nodes [
init(nodes[i])
}
}
- query.withFKs = true
query.Where(predicate.Node(func(s *sql.Selector) {
s.Where(sql.InValues(node.ChildrenColumn, fks...))
}))
@@ -504,13 +492,10 @@ func (nq *NodeQuery) loadChildren(ctx context.Context, query *NodeQuery, nodes [
return err
}
for _, n := range neighbors {
- fk := n.node_children
- if fk == nil {
- return fmt.Errorf(`foreign-key "node_children" is nil for node %v`, n.ID)
- }
- node, ok := nodeids[*fk]
+ fk := n.ParentID
+ node, ok := nodeids[fk]
if !ok {
- return fmt.Errorf(`unexpected foreign-key "node_children" returned %v for node %v`, *fk, n.ID)
+ return fmt.Errorf(`unexpected foreign-key "parent_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
diff --git a/examples/o2mrecur/ent/node_update.go b/examples/o2mrecur/ent/node_update.go
index d297c1db6..502808151 100644
--- a/examples/o2mrecur/ent/node_update.go
+++ b/examples/o2mrecur/ent/node_update.go
@@ -44,20 +44,26 @@ func (nu *NodeUpdate) AddValue(i int) *NodeUpdate {
return nu
}
-// SetParentID sets the "parent" edge to the Node entity by ID.
-func (nu *NodeUpdate) SetParentID(id int) *NodeUpdate {
- nu.mutation.SetParentID(id)
+// SetParentID sets the "parent_id" field.
+func (nu *NodeUpdate) SetParentID(i int) *NodeUpdate {
+ nu.mutation.SetParentID(i)
return nu
}
-// SetNillableParentID sets the "parent" edge to the Node entity by ID if the given value is not nil.
-func (nu *NodeUpdate) SetNillableParentID(id *int) *NodeUpdate {
- if id != nil {
- nu = nu.SetParentID(*id)
+// SetNillableParentID sets the "parent_id" field if the given value is not nil.
+func (nu *NodeUpdate) SetNillableParentID(i *int) *NodeUpdate {
+ if i != nil {
+ nu.SetParentID(*i)
}
return nu
}
+// ClearParentID clears the value of the "parent_id" field.
+func (nu *NodeUpdate) ClearParentID() *NodeUpdate {
+ nu.mutation.ClearParentID()
+ return nu
+}
+
// SetParent sets the "parent" edge to the Node entity.
func (nu *NodeUpdate) SetParent(n *Node) *NodeUpdate {
return nu.SetParentID(n.ID)
@@ -283,20 +289,26 @@ func (nuo *NodeUpdateOne) AddValue(i int) *NodeUpdateOne {
return nuo
}
-// SetParentID sets the "parent" edge to the Node entity by ID.
-func (nuo *NodeUpdateOne) SetParentID(id int) *NodeUpdateOne {
- nuo.mutation.SetParentID(id)
+// SetParentID sets the "parent_id" field.
+func (nuo *NodeUpdateOne) SetParentID(i int) *NodeUpdateOne {
+ nuo.mutation.SetParentID(i)
return nuo
}
-// SetNillableParentID sets the "parent" edge to the Node entity by ID if the given value is not nil.
-func (nuo *NodeUpdateOne) SetNillableParentID(id *int) *NodeUpdateOne {
- if id != nil {
- nuo = nuo.SetParentID(*id)
+// SetNillableParentID sets the "parent_id" field if the given value is not nil.
+func (nuo *NodeUpdateOne) SetNillableParentID(i *int) *NodeUpdateOne {
+ if i != nil {
+ nuo.SetParentID(*i)
}
return nuo
}
+// ClearParentID clears the value of the "parent_id" field.
+func (nuo *NodeUpdateOne) ClearParentID() *NodeUpdateOne {
+ nuo.mutation.ClearParentID()
+ return nuo
+}
+
// SetParent sets the "parent" edge to the Node entity.
func (nuo *NodeUpdateOne) SetParent(n *Node) *NodeUpdateOne {
return nuo.SetParentID(n.ID)
diff --git a/examples/o2mrecur/ent/schema/node.go b/examples/o2mrecur/ent/schema/node.go
index 06d3ff512..f53347364 100644
--- a/examples/o2mrecur/ent/schema/node.go
+++ b/examples/o2mrecur/ent/schema/node.go
@@ -19,6 +19,8 @@ type Node struct {
func (Node) Fields() []ent.Field {
return []ent.Field{
field.Int("value"),
+ field.Int("parent_id").
+ Optional(),
}
}
@@ -27,6 +29,7 @@ func (Node) Edges() []ent.Edge {
return []ent.Edge{
edge.To("children", Node.Type).
From("parent").
+ Field("parent_id").
Unique(),
}
}
diff --git a/examples/o2mrecur/example_test.go b/examples/o2mrecur/example_test.go
index 2830435e6..81686bea6 100644
--- a/examples/o2mrecur/example_test.go
+++ b/examples/o2mrecur/example_test.go
@@ -32,7 +32,7 @@ func Example_O2MRecur() {
// Output:
// Tree leafs [1 3 5]
// [1 3 5]
- // Node(id=1, value=2)
+ // Node(id=1, value=2, parent_id=0)
}
func Do(ctx context.Context, client *ent.Client) error {
@@ -96,7 +96,7 @@ func Do(ctx context.Context, client *ent.Client) error {
Where(node.Not(node.HasParent())).
OnlyX(ctx)
fmt.Println(orphan)
- // Output: Node(id=1, value=2)
+ // Output: Node(id=1, value=2, parent_id=0)
return nil
}
diff --git a/examples/o2orecur/ent/migrate/schema.go b/examples/o2orecur/ent/migrate/schema.go
index 1011218ad..52b6a4c2f 100644
--- a/examples/o2orecur/ent/migrate/schema.go
+++ b/examples/o2orecur/ent/migrate/schema.go
@@ -16,7 +16,7 @@ var (
NodesColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "value", Type: field.TypeInt},
- {Name: "node_next", Type: field.TypeInt, Unique: true, Nullable: true},
+ {Name: "prev_id", Type: field.TypeInt, Unique: true, Nullable: true},
}
// NodesTable holds the schema information for the "nodes" table.
NodesTable = &schema.Table{
diff --git a/examples/o2orecur/ent/mutation.go b/examples/o2orecur/ent/mutation.go
index 29e1fd502..78f06a9ca 100644
--- a/examples/o2orecur/ent/mutation.go
+++ b/examples/o2orecur/ent/mutation.go
@@ -203,9 +203,53 @@ func (m *NodeMutation) ResetValue() {
m.addvalue = nil
}
-// SetPrevID sets the "prev" edge to the Node entity by id.
-func (m *NodeMutation) SetPrevID(id int) {
- m.prev = &id
+// SetPrevID sets the "prev_id" field.
+func (m *NodeMutation) SetPrevID(i int) {
+ m.prev = &i
+}
+
+// PrevID returns the value of the "prev_id" field in the mutation.
+func (m *NodeMutation) PrevID() (r int, exists bool) {
+ v := m.prev
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldPrevID returns the old "prev_id" field's value of the Node entity.
+// If the Node 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 *NodeMutation) OldPrevID(ctx context.Context) (v int, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldPrevID is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldPrevID requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldPrevID: %w", err)
+ }
+ return oldValue.PrevID, nil
+}
+
+// ClearPrevID clears the value of the "prev_id" field.
+func (m *NodeMutation) ClearPrevID() {
+ m.prev = nil
+ m.clearedFields[node.FieldPrevID] = struct{}{}
+}
+
+// PrevIDCleared returns if the "prev_id" field was cleared in this mutation.
+func (m *NodeMutation) PrevIDCleared() bool {
+ _, ok := m.clearedFields[node.FieldPrevID]
+ return ok
+}
+
+// ResetPrevID resets all changes to the "prev_id" field.
+func (m *NodeMutation) ResetPrevID() {
+ m.prev = nil
+ delete(m.clearedFields, node.FieldPrevID)
}
// ClearPrev clears the "prev" edge to the Node entity.
@@ -215,15 +259,7 @@ func (m *NodeMutation) ClearPrev() {
// PrevCleared reports if the "prev" edge to the Node entity was cleared.
func (m *NodeMutation) PrevCleared() bool {
- return m.clearedprev
-}
-
-// PrevID returns the "prev" edge ID in the mutation.
-func (m *NodeMutation) PrevID() (id int, exists bool) {
- if m.prev != nil {
- return *m.prev, true
- }
- return
+ return m.PrevIDCleared() || m.clearedprev
}
// PrevIDs returns the "prev" edge IDs in the mutation.
@@ -315,10 +351,13 @@ func (m *NodeMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *NodeMutation) Fields() []string {
- fields := make([]string, 0, 1)
+ fields := make([]string, 0, 2)
if m.value != nil {
fields = append(fields, node.FieldValue)
}
+ if m.prev != nil {
+ fields = append(fields, node.FieldPrevID)
+ }
return fields
}
@@ -329,6 +368,8 @@ func (m *NodeMutation) Field(name string) (ent.Value, bool) {
switch name {
case node.FieldValue:
return m.Value()
+ case node.FieldPrevID:
+ return m.PrevID()
}
return nil, false
}
@@ -340,6 +381,8 @@ func (m *NodeMutation) OldField(ctx context.Context, name string) (ent.Value, er
switch name {
case node.FieldValue:
return m.OldValue(ctx)
+ case node.FieldPrevID:
+ return m.OldPrevID(ctx)
}
return nil, fmt.Errorf("unknown Node field %s", name)
}
@@ -356,6 +399,13 @@ func (m *NodeMutation) SetField(name string, value ent.Value) error {
}
m.SetValue(v)
return nil
+ case node.FieldPrevID:
+ v, ok := value.(int)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetPrevID(v)
+ return nil
}
return fmt.Errorf("unknown Node field %s", name)
}
@@ -400,7 +450,11 @@ func (m *NodeMutation) AddField(name string, value ent.Value) error {
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *NodeMutation) ClearedFields() []string {
- return nil
+ var fields []string
+ if m.FieldCleared(node.FieldPrevID) {
+ fields = append(fields, node.FieldPrevID)
+ }
+ return fields
}
// FieldCleared returns a boolean indicating if a field with the given name was
@@ -413,6 +467,11 @@ func (m *NodeMutation) FieldCleared(name string) bool {
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *NodeMutation) ClearField(name string) error {
+ switch name {
+ case node.FieldPrevID:
+ m.ClearPrevID()
+ return nil
+ }
return fmt.Errorf("unknown Node nullable field %s", name)
}
@@ -423,6 +482,9 @@ func (m *NodeMutation) ResetField(name string) error {
case node.FieldValue:
m.ResetValue()
return nil
+ case node.FieldPrevID:
+ m.ResetPrevID()
+ return nil
}
return fmt.Errorf("unknown Node field %s", name)
}
diff --git a/examples/o2orecur/ent/node.go b/examples/o2orecur/ent/node.go
index 7e7de15af..73b8e1413 100644
--- a/examples/o2orecur/ent/node.go
+++ b/examples/o2orecur/ent/node.go
@@ -21,10 +21,11 @@ type Node struct {
ID int `json:"id,omitempty"`
// Value holds the value of the "value" field.
Value int `json:"value,omitempty"`
+ // PrevID holds the value of the "prev_id" field.
+ PrevID int `json:"prev_id,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the NodeQuery when eager-loading is set.
- Edges NodeEdges `json:"edges"`
- node_next *int
+ Edges NodeEdges `json:"edges"`
}
// NodeEdges holds the relations/edges for other nodes in the graph.
@@ -69,9 +70,7 @@ func (*Node) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
- case node.FieldID, node.FieldValue:
- values[i] = new(sql.NullInt64)
- case node.ForeignKeys[0]: // node_next
+ case node.FieldID, node.FieldValue, node.FieldPrevID:
values[i] = new(sql.NullInt64)
default:
return nil, fmt.Errorf("unexpected column %q for type Node", columns[i])
@@ -100,12 +99,11 @@ func (n *Node) assignValues(columns []string, values []any) error {
} else if value.Valid {
n.Value = int(value.Int64)
}
- case node.ForeignKeys[0]:
+ case node.FieldPrevID:
if value, ok := values[i].(*sql.NullInt64); !ok {
- return fmt.Errorf("unexpected type %T for edge-field node_next", value)
+ return fmt.Errorf("unexpected type %T for field prev_id", values[i])
} else if value.Valid {
- n.node_next = new(int)
- *n.node_next = int(value.Int64)
+ n.PrevID = int(value.Int64)
}
}
}
@@ -147,6 +145,9 @@ func (n *Node) String() string {
builder.WriteString(fmt.Sprintf("id=%v, ", n.ID))
builder.WriteString("value=")
builder.WriteString(fmt.Sprintf("%v", n.Value))
+ builder.WriteString(", ")
+ builder.WriteString("prev_id=")
+ builder.WriteString(fmt.Sprintf("%v", n.PrevID))
builder.WriteByte(')')
return builder.String()
}
diff --git a/examples/o2orecur/ent/node/node.go b/examples/o2orecur/ent/node/node.go
index deb36152d..b93d51a59 100644
--- a/examples/o2orecur/ent/node/node.go
+++ b/examples/o2orecur/ent/node/node.go
@@ -13,6 +13,8 @@ const (
FieldID = "id"
// FieldValue holds the string denoting the value field in the database.
FieldValue = "value"
+ // FieldPrevID holds the string denoting the prev_id field in the database.
+ FieldPrevID = "prev_id"
// EdgePrev holds the string denoting the prev edge name in mutations.
EdgePrev = "prev"
// EdgeNext holds the string denoting the next edge name in mutations.
@@ -22,23 +24,18 @@ const (
// PrevTable is the table that holds the prev relation/edge.
PrevTable = "nodes"
// PrevColumn is the table column denoting the prev relation/edge.
- PrevColumn = "node_next"
+ PrevColumn = "prev_id"
// NextTable is the table that holds the next relation/edge.
NextTable = "nodes"
// NextColumn is the table column denoting the next relation/edge.
- NextColumn = "node_next"
+ NextColumn = "prev_id"
)
// Columns holds all SQL columns for node fields.
var Columns = []string{
FieldID,
FieldValue,
-}
-
-// ForeignKeys holds the SQL foreign-keys that are owned by the "nodes"
-// table and are not defined as standalone fields in the schema.
-var ForeignKeys = []string{
- "node_next",
+ FieldPrevID,
}
// ValidColumn reports if the column name is valid (part of the table columns).
@@ -48,10 +45,5 @@ func ValidColumn(column string) bool {
return true
}
}
- for i := range ForeignKeys {
- if column == ForeignKeys[i] {
- return true
- }
- }
return false
}
diff --git a/examples/o2orecur/ent/node/where.go b/examples/o2orecur/ent/node/where.go
index acf7ffa10..e046e9da9 100644
--- a/examples/o2orecur/ent/node/where.go
+++ b/examples/o2orecur/ent/node/where.go
@@ -62,6 +62,11 @@ func Value(v int) predicate.Node {
return predicate.Node(sql.FieldEQ(FieldValue, v))
}
+// PrevID applies equality check predicate on the "prev_id" field. It's identical to PrevIDEQ.
+func PrevID(v int) predicate.Node {
+ return predicate.Node(sql.FieldEQ(FieldPrevID, v))
+}
+
// ValueEQ applies the EQ predicate on the "value" field.
func ValueEQ(v int) predicate.Node {
return predicate.Node(sql.FieldEQ(FieldValue, v))
@@ -102,6 +107,36 @@ func ValueLTE(v int) predicate.Node {
return predicate.Node(sql.FieldLTE(FieldValue, v))
}
+// PrevIDEQ applies the EQ predicate on the "prev_id" field.
+func PrevIDEQ(v int) predicate.Node {
+ return predicate.Node(sql.FieldEQ(FieldPrevID, v))
+}
+
+// PrevIDNEQ applies the NEQ predicate on the "prev_id" field.
+func PrevIDNEQ(v int) predicate.Node {
+ return predicate.Node(sql.FieldNEQ(FieldPrevID, v))
+}
+
+// PrevIDIn applies the In predicate on the "prev_id" field.
+func PrevIDIn(vs ...int) predicate.Node {
+ return predicate.Node(sql.FieldIn(FieldPrevID, vs...))
+}
+
+// PrevIDNotIn applies the NotIn predicate on the "prev_id" field.
+func PrevIDNotIn(vs ...int) predicate.Node {
+ return predicate.Node(sql.FieldNotIn(FieldPrevID, vs...))
+}
+
+// PrevIDIsNil applies the IsNil predicate on the "prev_id" field.
+func PrevIDIsNil() predicate.Node {
+ return predicate.Node(sql.FieldIsNull(FieldPrevID))
+}
+
+// PrevIDNotNil applies the NotNil predicate on the "prev_id" field.
+func PrevIDNotNil() predicate.Node {
+ return predicate.Node(sql.FieldNotNull(FieldPrevID))
+}
+
// HasPrev applies the HasEdge predicate on the "prev" edge.
func HasPrev() predicate.Node {
return predicate.Node(func(s *sql.Selector) {
diff --git a/examples/o2orecur/ent/node_create.go b/examples/o2orecur/ent/node_create.go
index bf95e0876..c24b01f15 100644
--- a/examples/o2orecur/ent/node_create.go
+++ b/examples/o2orecur/ent/node_create.go
@@ -29,16 +29,16 @@ func (nc *NodeCreate) SetValue(i int) *NodeCreate {
return nc
}
-// SetPrevID sets the "prev" edge to the Node entity by ID.
-func (nc *NodeCreate) SetPrevID(id int) *NodeCreate {
- nc.mutation.SetPrevID(id)
+// SetPrevID sets the "prev_id" field.
+func (nc *NodeCreate) SetPrevID(i int) *NodeCreate {
+ nc.mutation.SetPrevID(i)
return nc
}
-// SetNillablePrevID sets the "prev" edge to the Node entity by ID if the given value is not nil.
-func (nc *NodeCreate) SetNillablePrevID(id *int) *NodeCreate {
- if id != nil {
- nc = nc.SetPrevID(*id)
+// SetNillablePrevID sets the "prev_id" field if the given value is not nil.
+func (nc *NodeCreate) SetNillablePrevID(i *int) *NodeCreate {
+ if i != nil {
+ nc.SetPrevID(*i)
}
return nc
}
@@ -157,7 +157,7 @@ func (nc *NodeCreate) createSpec() (*Node, *sqlgraph.CreateSpec) {
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
- _node.node_next = &nodes[0]
+ _node.PrevID = nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := nc.mutation.NextIDs(); len(nodes) > 0 {
diff --git a/examples/o2orecur/ent/node_query.go b/examples/o2orecur/ent/node_query.go
index 9e81b8371..c6db4575d 100644
--- a/examples/o2orecur/ent/node_query.go
+++ b/examples/o2orecur/ent/node_query.go
@@ -28,7 +28,6 @@ type NodeQuery struct {
predicates []predicate.Node
withPrev *NodeQuery
withNext *NodeQuery
- withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@@ -406,19 +405,12 @@ func (nq *NodeQuery) prepareQuery(ctx context.Context) error {
func (nq *NodeQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Node, error) {
var (
nodes = []*Node{}
- withFKs = nq.withFKs
_spec = nq.querySpec()
loadedTypes = [2]bool{
nq.withPrev != nil,
nq.withNext != nil,
}
)
- if nq.withPrev != nil {
- withFKs = true
- }
- if withFKs {
- _spec.Node.Columns = append(_spec.Node.Columns, node.ForeignKeys...)
- }
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*Node).scanValues(nil, columns)
}
@@ -456,10 +448,7 @@ func (nq *NodeQuery) loadPrev(ctx context.Context, query *NodeQuery, nodes []*No
ids := make([]int, 0, len(nodes))
nodeids := make(map[int][]*Node)
for i := range nodes {
- if nodes[i].node_next == nil {
- continue
- }
- fk := *nodes[i].node_next
+ fk := nodes[i].PrevID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
@@ -476,7 +465,7 @@ func (nq *NodeQuery) loadPrev(ctx context.Context, query *NodeQuery, nodes []*No
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
- return fmt.Errorf(`unexpected foreign-key "node_next" returned %v`, n.ID)
+ return fmt.Errorf(`unexpected foreign-key "prev_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
@@ -491,7 +480,6 @@ func (nq *NodeQuery) loadNext(ctx context.Context, query *NodeQuery, nodes []*No
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
}
- query.withFKs = true
query.Where(predicate.Node(func(s *sql.Selector) {
s.Where(sql.InValues(node.NextColumn, fks...))
}))
@@ -500,13 +488,10 @@ func (nq *NodeQuery) loadNext(ctx context.Context, query *NodeQuery, nodes []*No
return err
}
for _, n := range neighbors {
- fk := n.node_next
- if fk == nil {
- return fmt.Errorf(`foreign-key "node_next" is nil for node %v`, n.ID)
- }
- node, ok := nodeids[*fk]
+ fk := n.PrevID
+ node, ok := nodeids[fk]
if !ok {
- return fmt.Errorf(`unexpected foreign-key "node_next" returned %v for node %v`, *fk, n.ID)
+ return fmt.Errorf(`unexpected foreign-key "prev_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
diff --git a/examples/o2orecur/ent/node_update.go b/examples/o2orecur/ent/node_update.go
index 6bfa2afa0..83d6be499 100644
--- a/examples/o2orecur/ent/node_update.go
+++ b/examples/o2orecur/ent/node_update.go
@@ -44,20 +44,26 @@ func (nu *NodeUpdate) AddValue(i int) *NodeUpdate {
return nu
}
-// SetPrevID sets the "prev" edge to the Node entity by ID.
-func (nu *NodeUpdate) SetPrevID(id int) *NodeUpdate {
- nu.mutation.SetPrevID(id)
+// SetPrevID sets the "prev_id" field.
+func (nu *NodeUpdate) SetPrevID(i int) *NodeUpdate {
+ nu.mutation.SetPrevID(i)
return nu
}
-// SetNillablePrevID sets the "prev" edge to the Node entity by ID if the given value is not nil.
-func (nu *NodeUpdate) SetNillablePrevID(id *int) *NodeUpdate {
- if id != nil {
- nu = nu.SetPrevID(*id)
+// SetNillablePrevID sets the "prev_id" field if the given value is not nil.
+func (nu *NodeUpdate) SetNillablePrevID(i *int) *NodeUpdate {
+ if i != nil {
+ nu.SetPrevID(*i)
}
return nu
}
+// ClearPrevID clears the value of the "prev_id" field.
+func (nu *NodeUpdate) ClearPrevID() *NodeUpdate {
+ nu.mutation.ClearPrevID()
+ return nu
+}
+
// SetPrev sets the "prev" edge to the Node entity.
func (nu *NodeUpdate) SetPrev(n *Node) *NodeUpdate {
return nu.SetPrevID(n.ID)
@@ -253,20 +259,26 @@ func (nuo *NodeUpdateOne) AddValue(i int) *NodeUpdateOne {
return nuo
}
-// SetPrevID sets the "prev" edge to the Node entity by ID.
-func (nuo *NodeUpdateOne) SetPrevID(id int) *NodeUpdateOne {
- nuo.mutation.SetPrevID(id)
+// SetPrevID sets the "prev_id" field.
+func (nuo *NodeUpdateOne) SetPrevID(i int) *NodeUpdateOne {
+ nuo.mutation.SetPrevID(i)
return nuo
}
-// SetNillablePrevID sets the "prev" edge to the Node entity by ID if the given value is not nil.
-func (nuo *NodeUpdateOne) SetNillablePrevID(id *int) *NodeUpdateOne {
- if id != nil {
- nuo = nuo.SetPrevID(*id)
+// SetNillablePrevID sets the "prev_id" field if the given value is not nil.
+func (nuo *NodeUpdateOne) SetNillablePrevID(i *int) *NodeUpdateOne {
+ if i != nil {
+ nuo.SetPrevID(*i)
}
return nuo
}
+// ClearPrevID clears the value of the "prev_id" field.
+func (nuo *NodeUpdateOne) ClearPrevID() *NodeUpdateOne {
+ nuo.mutation.ClearPrevID()
+ return nuo
+}
+
// SetPrev sets the "prev" edge to the Node entity.
func (nuo *NodeUpdateOne) SetPrev(n *Node) *NodeUpdateOne {
return nuo.SetPrevID(n.ID)
diff --git a/examples/o2orecur/ent/schema/node.go b/examples/o2orecur/ent/schema/node.go
index 93a43dcac..6bd99d405 100644
--- a/examples/o2orecur/ent/schema/node.go
+++ b/examples/o2orecur/ent/schema/node.go
@@ -19,6 +19,8 @@ type Node struct {
func (Node) Fields() []ent.Field {
return []ent.Field{
field.Int("value"),
+ field.Int("prev_id").
+ Optional(),
}
}
@@ -28,6 +30,7 @@ func (Node) Edges() []ent.Edge {
edge.To("next", Node.Type).
Unique().
From("prev").
+ Field("prev_id").
Unique(),
}
}