type safe predicates

Reviewed By: alexsn

Differential Revision: D16452717

fbshipit-source-id: da0a07275434d95d73a5a26830a2e5535c3abf47
This commit is contained in:
Ariel Mashraki
2019-07-24 08:32:29 -07:00
committed by Facebook Github Bot
parent ff6403b4ae
commit 2cfda7564f
82 changed files with 4106 additions and 3422 deletions

View File

@@ -5,107 +5,109 @@ package boring
import (
"strconv"
"fbc/ent"
"fbc/ent/entc/integration/plugin/ent/predicate"
"fbc/ent/dialect/gremlin/graph/dsl"
"fbc/ent/dialect/gremlin/graph/dsl/__"
"fbc/ent/dialect/gremlin/graph/dsl/p"
"fbc/ent/dialect/sql"
)
// ID filters vertices based on their identifier.
func ID(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func ID(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
id, _ := strconv.Atoi(id)
s.Where(sql.EQ(s.C(FieldID), id))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(id)
},
}
)
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDEQ(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
v, _ := strconv.Atoi(id)
s.Where(sql.EQ(s.C(FieldID), v))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(p.EQ(id))
},
}
)
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDNEQ(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
v, _ := strconv.Atoi(id)
s.Where(sql.NEQ(s.C(FieldID), v))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(p.NEQ(id))
},
}
)
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDGT(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
v, _ := strconv.Atoi(id)
s.Where(sql.GT(s.C(FieldID), v))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(p.GT(id))
},
}
)
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDGTE(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
v, _ := strconv.Atoi(id)
s.Where(sql.GTE(s.C(FieldID), v))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(p.GTE(id))
},
}
)
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDLT(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
v, _ := strconv.Atoi(id)
s.Where(sql.LT(s.C(FieldID), v))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(p.LT(id))
},
}
)
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDLTE(id string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
v, _ := strconv.Atoi(id)
s.Where(sql.LTE(s.C(FieldID), v))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
t.HasID(p.LTE(id))
},
}
)
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDIn(ids ...string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
@@ -118,20 +120,20 @@ func IDIn(ids ...string) ent.Predicate {
}
s.Where(sql.In(s.C(FieldID), v...))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
t.HasID(p.Within(v...))
},
}
)
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
func IDNotIn(ids ...string) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
@@ -144,12 +146,49 @@ func IDNotIn(ids ...string) ent.Predicate {
}
s.Where(sql.NotIn(s.C(FieldID), v...))
},
Gremlin: func(t *dsl.Traversal) {
func(t *dsl.Traversal) {
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
t.HasID(p.Without(v...))
},
}
)
}
// Or groups list of predicates with the or operator between them.
func Or(predicates ...predicate.Boring) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
for i, p := range predicates {
if i > 0 {
s.Or()
}
p(s)
}
},
func(tr *dsl.Traversal) {
trs := make([]interface{}, 0, len(predicates))
for _, p := range predicates {
t := __.New()
p(t)
trs = append(trs, t)
}
tr.Where(__.Or(trs...))
},
)
}
// Not applies the not operator on the given predicate.
func Not(p predicate.Boring) predicate.Boring {
return predicate.BoringPerDialect(
func(s *sql.Selector) {
p(s.Not())
},
func(tr *dsl.Traversal) {
t := __.New()
p(t)
tr.Where(__.Not(t))
},
)
}

View File

@@ -7,8 +7,8 @@ import (
"errors"
"fbc/ent/entc/integration/plugin/ent/boring"
"fbc/ent/entc/integration/plugin/ent/predicate"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/gremlin"
"fbc/ent/dialect/gremlin/graph/dsl"
@@ -19,11 +19,11 @@ import (
// BoringDelete is the builder for deleting a Boring entity.
type BoringDelete struct {
config
predicates []ent.Predicate
predicates []predicate.Boring
}
// Where adds a new predicate for the builder.
func (bd *BoringDelete) Where(ps ...ent.Predicate) *BoringDelete {
func (bd *BoringDelete) Where(ps ...predicate.Boring) *BoringDelete {
bd.predicates = append(bd.predicates, ps...)
return bd
}
@@ -51,7 +51,7 @@ func (bd *BoringDelete) sqlExec(ctx context.Context) error {
var res sql.Result
selector := sql.Select().From(sql.Table(boring.Table))
for _, p := range bd.predicates {
p.SQL(selector)
p(selector)
}
query, args := sql.Delete(boring.Table).FromSelect(selector).Query()
return bd.driver.Exec(ctx, query, args, &res)
@@ -66,7 +66,7 @@ func (bd *BoringDelete) gremlinExec(ctx context.Context) error {
func (bd *BoringDelete) gremlin() *dsl.Traversal {
t := g.V().HasLabel(boring.Label)
for _, p := range bd.predicates {
p.Gremlin(t)
p(t)
}
return t.Drop()
}

View File

@@ -9,8 +9,8 @@ import (
"math"
"fbc/ent/entc/integration/plugin/ent/boring"
"fbc/ent/entc/integration/plugin/ent/predicate"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/gremlin"
"fbc/ent/dialect/gremlin/graph/dsl"
@@ -26,14 +26,14 @@ type BoringQuery struct {
offset *int
order []Order
unique []string
predicates []ent.Predicate
predicates []predicate.Boring
// intermediate queries.
sql *sql.Selector
gremlin *dsl.Traversal
}
// Where adds a new predicate for the builder.
func (bq *BoringQuery) Where(ps ...ent.Predicate) *BoringQuery {
func (bq *BoringQuery) Where(ps ...predicate.Boring) *BoringQuery {
bq.predicates = append(bq.predicates, ps...)
return bq
}
@@ -257,7 +257,7 @@ func (bq *BoringQuery) Clone() *BoringQuery {
offset: bq.offset,
order: append([]Order{}, bq.order...),
unique: append([]string{}, bq.unique...),
predicates: append([]ent.Predicate{}, bq.predicates...),
predicates: append([]predicate.Boring{}, bq.predicates...),
// clone intermediate queries.
sql: bq.sql.Clone(),
gremlin: bq.gremlin.Clone(),
@@ -348,7 +348,7 @@ func (bq *BoringQuery) sqlQuery() *sql.Selector {
selector.Select(selector.Columns(boring.Columns...)...)
}
for _, p := range bq.predicates {
p.SQL(selector)
p(selector)
}
for _, p := range bq.order {
p.SQL(selector)
@@ -419,7 +419,7 @@ func (bq *BoringQuery) gremlinQuery() *dsl.Traversal {
v = bq.gremlin.Clone()
}
for _, p := range bq.predicates {
p.Gremlin(v)
p(v)
}
if len(bq.order) > 0 {
v.Order()

View File

@@ -8,8 +8,8 @@ import (
"fmt"
"fbc/ent/entc/integration/plugin/ent/boring"
"fbc/ent/entc/integration/plugin/ent/predicate"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/gremlin"
"fbc/ent/dialect/gremlin/graph/dsl"
@@ -20,11 +20,11 @@ import (
// BoringUpdate is the builder for updating Boring entities.
type BoringUpdate struct {
config
predicates []ent.Predicate
predicates []predicate.Boring
}
// Where adds a new predicate for the builder.
func (bu *BoringUpdate) Where(ps ...ent.Predicate) *BoringUpdate {
func (bu *BoringUpdate) Where(ps ...predicate.Boring) *BoringUpdate {
bu.predicates = append(bu.predicates, ps...)
return bu
}
@@ -67,7 +67,7 @@ func (bu *BoringUpdate) ExecX(ctx context.Context) {
func (bu *BoringUpdate) sqlSave(ctx context.Context) (n int, err error) {
selector := sql.Select(boring.FieldID).From(sql.Table(boring.Table))
for _, p := range bu.predicates {
p.SQL(selector)
p(selector)
}
rows := &sql.Rows{}
query, args := selector.Query()
@@ -117,7 +117,7 @@ func (bu *BoringUpdate) gremlinSave(ctx context.Context) ([]*Boring, error) {
func (bu *BoringUpdate) gremlin() *dsl.Traversal {
v := g.V().HasLabel(boring.Label)
for _, p := range bu.predicates {
p.Gremlin(v)
p(v)
}
var (
trs []*dsl.Traversal
@@ -169,7 +169,7 @@ func (buo *BoringUpdateOne) ExecX(ctx context.Context) {
func (buo *BoringUpdateOne) sqlSave(ctx context.Context) (b *Boring, err error) {
selector := sql.Select(boring.Columns...).From(sql.Table(boring.Table))
boring.ID(buo.id).SQL(selector)
boring.ID(buo.id)(selector)
rows := &sql.Rows{}
query, args := selector.Query()
if err = buo.driver.Query(ctx, query, args, rows); err != nil {

View File

@@ -7,7 +7,6 @@ import (
"strconv"
"strings"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/gremlin"
"fbc/ent/dialect/gremlin/encoding/graphson"
@@ -16,49 +15,12 @@ import (
"fbc/ent/dialect/sql"
)
// Predicate is an alias to ent.Predicate.
type Predicate = ent.Predicate
// Or groups list of predicates with the or operator between them.
func Or(predicates ...ent.Predicate) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
for i, p := range predicates {
if i > 0 {
s.Or()
}
p.SQL(s)
}
},
Gremlin: func(tr *dsl.Traversal) {
trs := make([]interface{}, 0, len(predicates))
for _, p := range predicates {
t := __.New()
p.Gremlin(t)
trs = append(trs, t)
}
tr.Where(__.Or(trs...))
},
}
// Order applies an ordering on either graph traversal or sql selector.
type Order struct {
SQL func(*sql.Selector)
Gremlin func(*dsl.Traversal)
}
// Not applies the not operator on the given predicate.
func Not(p ent.Predicate) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
p.SQL(s.Not())
},
Gremlin: func(tr *dsl.Traversal) {
t := __.New()
p.Gremlin(t)
tr.Where(__.Not(t))
},
}
}
// Order applies an ordering on the traversal.
type Order ent.Predicate
// Asc applies the given fields in ASC order.
func Asc(fields ...string) Order {
return Order{

View File

@@ -0,0 +1,26 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package predicate
import (
"fbc/ent/dialect/gremlin/graph/dsl"
"fbc/ent/dialect/sql"
"fmt"
)
// Boring is the predicate function for boring builders.
type Boring func(interface{})
// BoringPerDialect construct a predicate for both gremlin traversal and sql selector.
func BoringPerDialect(f1 func(*sql.Selector), f2 func(*dsl.Traversal)) Boring {
return Boring(func(v interface{}) {
switch v := v.(type) {
case *sql.Selector:
f1(v)
case *dsl.Traversal:
f2(v)
default:
panic(fmt.Sprintf("unknown type for predicate: %T", v))
}
})
}