mirror of
https://github.com/ent/ent.git
synced 2026-05-22 09:31:45 +03:00
Summary: Pull Request resolved: https://github.com/facebookincubator/ent/pull/154 Loading the "form" table is not required where there's no predicate on the join. Reviewed By: alexsn Differential Revision: D18421062 fbshipit-source-id: cb2a045a5a8a76ea4f07e5cf4305a6da338a616e
105 lines
2.8 KiB
Go
105 lines
2.8 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 sql
|
|
|
|
// Rel is a relation type of an edge.
|
|
type Rel int
|
|
|
|
// Relation types.
|
|
const (
|
|
Unk Rel = iota // Unknown.
|
|
O2O // One to one / has one.
|
|
O2M // One to many / has many.
|
|
M2O // Many to one (inverse perspective for O2M).
|
|
M2M // Many to many.
|
|
)
|
|
|
|
// String returns the relation name.
|
|
func (r Rel) String() (s string) {
|
|
switch r {
|
|
case O2O:
|
|
s = "O2O"
|
|
case O2M:
|
|
s = "O2M"
|
|
case M2O:
|
|
s = "M2O"
|
|
case M2M:
|
|
s = "M2M"
|
|
default:
|
|
s = "Unknown"
|
|
}
|
|
return s
|
|
}
|
|
|
|
// A Step provides a path-step information to the traversal functions.
|
|
type Step struct {
|
|
// From is the source of the step.
|
|
From struct {
|
|
// V can be either one vertex or set of vertices.
|
|
// It can be a pre-processed step (sql.Query) or a simple Go type (integer or string).
|
|
V interface{}
|
|
// Table holds the table name of V (from).
|
|
Table string
|
|
// Column to join with. Usually the "id" column.
|
|
Column string
|
|
}
|
|
// Edge holds the edge information for getting the neighbors.
|
|
Edge struct {
|
|
// Rel of the edge.
|
|
Rel Rel
|
|
// Table name of where this edge columns reside.
|
|
Table string
|
|
// Columns of the edge.
|
|
// In O2O and M2O, it holds the foreign-key column. Hence, len == 1.
|
|
// In M2M, it holds the primary-key columns of the join table. Hence, len == 2.
|
|
Columns []string
|
|
// Inverse indicates if the edge is an inverse edge.
|
|
Inverse bool
|
|
}
|
|
// To is the dest of the path (the neighbors).
|
|
To struct {
|
|
// Table holds the table name of the neighbors (to).
|
|
Table string
|
|
// Column to join with. Usually the "id" column.
|
|
Column string
|
|
}
|
|
}
|
|
|
|
// Neighbors returns a Selector for evaluating the path-step
|
|
// and getting the neighbors of one or more vertices.
|
|
func Neighbors(dialect string, s *Step) (q *Selector) {
|
|
builder := Dialect(dialect)
|
|
switch r := s.Edge.Rel; {
|
|
case r == M2M:
|
|
pk1, pk2 := s.Edge.Columns[1], s.Edge.Columns[0]
|
|
if s.Edge.Inverse {
|
|
pk1, pk2 = pk2, pk1
|
|
}
|
|
to := builder.Table(s.To.Table)
|
|
join := builder.Table(s.Edge.Table)
|
|
match := builder.Select(join.C(pk1)).
|
|
From(join).
|
|
Where(EQ(join.C(pk2), s.From.V))
|
|
q = builder.Select().
|
|
From(to).
|
|
Join(match).
|
|
On(to.C(s.To.Column), match.C(pk1))
|
|
case r == M2O || (r == O2O && s.Edge.Inverse):
|
|
t1 := builder.Table(s.To.Table)
|
|
t2 := builder.Select(s.Edge.Columns[0]).
|
|
From(builder.Table(s.Edge.Table)).
|
|
Where(EQ(s.From.Column, s.From.V))
|
|
q = builder.Select().
|
|
From(t1).
|
|
Join(t2).
|
|
On(t1.C(s.From.Column), t2.C(s.Edge.Columns[0]))
|
|
case r == O2M || (r == O2O && !s.Edge.Inverse):
|
|
q = builder.Select().
|
|
From(builder.Table(s.To.Table)).
|
|
Where(EQ(s.Edge.Columns[0], s.From.V))
|
|
}
|
|
return q
|
|
}
|