dialect/sql/schema: universl id allocation support

Summary: Pull Request resolved: https://github.com/facebookincubator/ent/pull/9

Reviewed By: alexsn

Differential Revision: D16252229

fbshipit-source-id: 795b6556d322e5c1ff5fb826c3b06ba5421ac857
This commit is contained in:
Ariel Mashraki
2019-07-15 02:26:54 -07:00
committed by Facebook Github Bot
parent ad051e6d72
commit b5cdb810b8
57 changed files with 4164 additions and 964 deletions

View File

@@ -0,0 +1,20 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv1
import (
"context"
)
type contextKey struct{}
// FromContext returns the Client stored in a context, or nil if there isn't one.
func FromContext(ctx context.Context) *Client {
c, _ := ctx.Value(contextKey{}).(*Client)
return c
}
// NewContext returns a new context with the given Client attached.
func NewContext(parent context.Context, c *Client) context.Context {
return context.WithValue(parent, contextKey{}, c)
}

View File

@@ -3,31 +3,27 @@
package migrate
import (
"context"
"fmt"
"fbc/ent/dialect"
"fbc/ent/dialect/sql/schema"
"fbc/ent/field"
)
var (
nullable = true
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "age", Type: field.TypeInt32},
{Name: "name", Type: field.TypeString, Size: 10},
{Name: "address", Type: field.TypeString},
}
// UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{
Name: "users",
Columns: UsersColumns,
PrimaryKey: []*schema.Column{UsersColumns[0]},
ForeignKeys: []*schema.ForeignKey{},
}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
UsersTable,
}
)
func init() {
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv dialect.Driver
universalID bool
}
// NewSchema creates a new schema client.
func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
// Create creates all schema resources.
func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
migrate, err := schema.NewMigrate(s.drv, opts...)
if err != nil {
return fmt.Errorf("ent/migrate: %v", err)
}
return migrate.Create(ctx, Tables...)
}

View File

@@ -3,39 +3,31 @@
package migrate
import (
"context"
"fmt"
"fbc/ent/dialect"
"fbc/ent/dialect/sql/schema"
"fbc/ent/field"
)
// SQLDialect wraps the dialect.Driver with additional migration methods.
type SQLDriver interface {
Create(context.Context, ...*schema.Table) error
}
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv SQLDriver
}
// NewSchema creates a new schema client.
func NewSchema(drv dialect.Driver) *Schema {
s := &Schema{}
switch drv.Dialect() {
case dialect.MySQL:
s.drv = &schema.MySQL{Driver: drv}
case dialect.SQLite:
s.drv = &schema.SQLite{Driver: drv}
var (
nullable = true
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "age", Type: field.TypeInt32},
{Name: "name", Type: field.TypeString, Size: 10},
{Name: "address", Type: field.TypeString},
}
return s
}
// Create creates all schema resources.
func (s *Schema) Create(ctx context.Context) error {
if s.drv == nil {
return fmt.Errorf("entv1/migrate: dialect does not support migration")
// UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{
Name: "users",
Columns: UsersColumns,
PrimaryKey: []*schema.Column{UsersColumns[0]},
ForeignKeys: []*schema.ForeignKey{},
}
return s.drv.Create(ctx, Tables...)
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
UsersTable,
}
)
func init() {
}

View File

@@ -93,8 +93,8 @@ func (u *User) Unwrap() *User {
func (u *User) String() string {
buf := bytes.NewBuffer(nil)
buf.WriteString("User(")
buf.WriteString(fmt.Sprintf("id=%v,", u.ID))
buf.WriteString(fmt.Sprintf("age=%v", u.Age))
buf.WriteString(fmt.Sprintf("id=%v", u.ID))
buf.WriteString(fmt.Sprintf(", age=%v", u.Age))
buf.WriteString(fmt.Sprintf(", name=%v", u.Name))
buf.WriteString(fmt.Sprintf(", address=%v", u.Address))
buf.WriteString(")")

View File

@@ -9,6 +9,8 @@ import (
"fbc/ent/entc/integration/migrate/entv2/migrate"
"fbc/ent/entc/integration/migrate/entv2/group"
"fbc/ent/entc/integration/migrate/entv2/pet"
"fbc/ent/entc/integration/migrate/entv2/user"
)
@@ -17,6 +19,10 @@ type Client struct {
config
// Schema is the client for creating, migrating and dropping schema.
Schema *migrate.Schema
// Group is the client for interacting with the Group builders.
Group *GroupClient
// Pet is the client for interacting with the Pet builders.
Pet *PetClient
// User is the client for interacting with the User builders.
User *UserClient
}
@@ -28,6 +34,8 @@ func NewClient(opts ...Option) *Client {
return &Client{
config: c,
Schema: migrate.NewSchema(c.driver),
Group: NewGroupClient(c),
Pet: NewPetClient(c),
User: NewUserClient(c),
}
}
@@ -44,10 +52,112 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
cfg := config{driver: tx, log: c.log, verbose: c.verbose}
return &Tx{
config: cfg,
Group: NewGroupClient(cfg),
Pet: NewPetClient(cfg),
User: NewUserClient(cfg),
}, nil
}
// GroupClient is a client for the Group schema.
type GroupClient struct {
config
}
// NewGroupClient returns a client for the Group from the given config.
func NewGroupClient(c config) *GroupClient {
return &GroupClient{config: c}
}
// Create returns a create builder for Group.
func (c *GroupClient) Create() *GroupCreate {
return &GroupCreate{config: c.config}
}
// Update returns an update builder for Group.
func (c *GroupClient) Update() *GroupUpdate {
return &GroupUpdate{config: c.config}
}
// UpdateOne returns an update builder for the given entity.
func (c *GroupClient) UpdateOne(gr *Group) *GroupUpdateOne {
return c.UpdateOneID(gr.ID)
}
// UpdateOneID returns an update builder for the given id.
func (c *GroupClient) UpdateOneID(id string) *GroupUpdateOne {
return &GroupUpdateOne{config: c.config, id: id}
}
// Delete returns a delete builder for Group.
func (c *GroupClient) Delete() *GroupDelete {
return &GroupDelete{config: c.config}
}
// DeleteOne returns a delete builder for the given entity.
func (c *GroupClient) DeleteOne(gr *Group) *GroupDeleteOne {
return c.DeleteOneID(gr.ID)
}
// DeleteOneID returns a delete builder for the given id.
func (c *GroupClient) DeleteOneID(id string) *GroupDeleteOne {
return &GroupDeleteOne{c.Delete().Where(group.ID(id))}
}
// Create returns a query builder for Group.
func (c *GroupClient) Query() *GroupQuery {
return &GroupQuery{config: c.config}
}
// PetClient is a client for the Pet schema.
type PetClient struct {
config
}
// NewPetClient returns a client for the Pet from the given config.
func NewPetClient(c config) *PetClient {
return &PetClient{config: c}
}
// Create returns a create builder for Pet.
func (c *PetClient) Create() *PetCreate {
return &PetCreate{config: c.config}
}
// Update returns an update builder for Pet.
func (c *PetClient) Update() *PetUpdate {
return &PetUpdate{config: c.config}
}
// UpdateOne returns an update builder for the given entity.
func (c *PetClient) UpdateOne(pe *Pet) *PetUpdateOne {
return c.UpdateOneID(pe.ID)
}
// UpdateOneID returns an update builder for the given id.
func (c *PetClient) UpdateOneID(id string) *PetUpdateOne {
return &PetUpdateOne{config: c.config, id: id}
}
// Delete returns a delete builder for Pet.
func (c *PetClient) Delete() *PetDelete {
return &PetDelete{config: c.config}
}
// DeleteOne returns a delete builder for the given entity.
func (c *PetClient) DeleteOne(pe *Pet) *PetDeleteOne {
return c.DeleteOneID(pe.ID)
}
// DeleteOneID returns a delete builder for the given id.
func (c *PetClient) DeleteOneID(id string) *PetDeleteOne {
return &PetDeleteOne{c.Delete().Where(pet.ID(id))}
}
// Create returns a query builder for Pet.
func (c *PetClient) Query() *PetQuery {
return &PetQuery{config: c.config}
}
// UserClient is a client for the User schema.
type UserClient struct {
config

View File

@@ -0,0 +1,20 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
)
type contextKey struct{}
// FromContext returns the Client stored in a context, or nil if there isn't one.
func FromContext(ctx context.Context) *Client {
c, _ := ctx.Value(contextKey{}).(*Client)
return c
}
// NewContext returns a new context with the given Client attached.
func NewContext(parent context.Context, c *Client) context.Context {
return context.WithValue(parent, contextKey{}, c)
}

View File

@@ -26,6 +26,52 @@ func init() {
}
}
func ExampleGroup() {
if endpoint == nil {
return
}
ctx := context.Background()
conn, err := gremlin.NewClient(gremlin.Config{Endpoint: *endpoint})
if err != nil {
log.Fatalf("failed creating database client: %v", err)
}
client := NewClient(Driver(dialect.NewGremlin(conn)))
// creating vertices for the group's edges.
// create group vertex with its edges.
gr := client.Group.
Create().
SaveX(ctx)
log.Println("group created:", gr)
// query edges.
// Output:
}
func ExamplePet() {
if endpoint == nil {
return
}
ctx := context.Background()
conn, err := gremlin.NewClient(gremlin.Config{Endpoint: *endpoint})
if err != nil {
log.Fatalf("failed creating database client: %v", err)
}
client := NewClient(Driver(dialect.NewGremlin(conn)))
// creating vertices for the pet's edges.
// create pet vertex with its edges.
pe := client.Pet.
Create().
SaveX(ctx)
log.Println("pet created:", pe)
// query edges.
// Output:
}
func ExampleUser() {
if endpoint == nil {
return

View File

@@ -0,0 +1,125 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"bytes"
"fmt"
"strconv"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
)
// Group is the model entity for the Group schema.
type Group struct {
config
// ID of the ent.
ID string `json:"id,omitempty"`
}
// FromResponse scans the gremlin response data into Group.
func (gr *Group) FromResponse(res *gremlin.Response) error {
vmap, err := res.ReadValueMap()
if err != nil {
return err
}
var vgr struct {
ID string `json:"id,omitempty"`
}
if err := vmap.Decode(&vgr); err != nil {
return err
}
gr.ID = vgr.ID
return nil
}
// FromRows scans the sql response data into Group.
func (gr *Group) FromRows(rows *sql.Rows) error {
var vgr struct {
ID int
}
// the order here should be the same as in the `group.Columns`.
if err := rows.Scan(
&vgr.ID,
); err != nil {
return err
}
gr.ID = strconv.Itoa(vgr.ID)
return nil
}
// Update returns a builder for updating this Group.
// Note that, you need to call Group.Unwrap() before calling this method, if this Group
// was returned from a transaction, and the transaction was committed or rolled back.
func (gr *Group) Update() *GroupUpdateOne {
return (&GroupClient{gr.config}).UpdateOne(gr)
}
// Unwrap unwraps the entity that was returned from a transaction after it was closed,
// so that all next queries will be executed through the driver which created the transaction.
func (gr *Group) Unwrap() *Group {
tx, ok := gr.config.driver.(*txDriver)
if !ok {
panic("entv2: Group is not a transactional entity")
}
gr.config.driver = tx.drv
return gr
}
// String implements the fmt.Stringer.
func (gr *Group) String() string {
buf := bytes.NewBuffer(nil)
buf.WriteString("Group(")
buf.WriteString(fmt.Sprintf("id=%v", gr.ID))
buf.WriteString(")")
return buf.String()
}
// id returns the int representation of the ID field.
func (gr *Group) id() int {
id, _ := strconv.Atoi(gr.ID)
return id
}
// Groups is a parsable slice of Group.
type Groups []*Group
// FromResponse scans the gremlin response data into Groups.
func (gr *Groups) FromResponse(res *gremlin.Response) error {
vmap, err := res.ReadValueMap()
if err != nil {
return err
}
var vgr []struct {
ID string `json:"id,omitempty"`
}
if err := vmap.Decode(&vgr); err != nil {
return err
}
for _, v := range vgr {
*gr = append(*gr, &Group{
ID: v.ID,
})
}
return nil
}
// FromRows scans the sql response data into Groups.
func (gr *Groups) FromRows(rows *sql.Rows) error {
for rows.Next() {
vgr := &Group{}
if err := vgr.FromRows(rows); err != nil {
return err
}
*gr = append(*gr, vgr)
}
return nil
}
func (gr Groups) config(cfg config) {
for i := range gr {
gr[i].config = cfg
}
}

View File

@@ -0,0 +1,17 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package group
const (
// Label holds the string label denoting the group type in the database.
Label = "group"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// Table holds the table name of the group in the database.
Table = "groups"
)
// Columns holds all SQL columns are group fields.
var Columns = []string{
FieldID,
}

View File

@@ -0,0 +1,156 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package group
import (
"strconv"
"fbc/ent"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/p"
)
// ID filters vertices based on their identifier.
func ID(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
id, _ := strconv.Atoi(id)
s.Where(sql.EQ(s.C(FieldID), id))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.EQ(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.NEQ(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.GT(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.GTE(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.LT(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.LTE(s.C(FieldID), v))
},
Gremlin: 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) {
// 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 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i], _ = strconv.Atoi(ids[i])
}
s.Where(sql.In(s.C(FieldID), v...))
},
Gremlin: 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) {
// 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 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i], _ = strconv.Atoi(ids[i])
}
s.Where(sql.NotIn(s.C(FieldID), v...))
},
Gremlin: func(t *dsl.Traversal) {
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
t.HasID(p.Without(v...))
},
}
}

View File

@@ -0,0 +1,90 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"strconv"
"fbc/ent/entc/integration/migrate/entv2/group"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// GroupCreate is the builder for creating a Group entity.
type GroupCreate struct {
config
}
// Save creates the Group in the database.
func (gc *GroupCreate) Save(ctx context.Context) (*Group, error) {
switch gc.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gc.sqlSave(ctx)
case dialect.Neptune:
return gc.gremlinSave(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// SaveX calls Save and panics if Save returns an error.
func (gc *GroupCreate) SaveX(ctx context.Context) *Group {
v, err := gc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
func (gc *GroupCreate) sqlSave(ctx context.Context) (*Group, error) {
var (
res sql.Result
gr = &Group{config: gc.config}
)
tx, err := gc.driver.Tx(ctx)
if err != nil {
return nil, err
}
builder := sql.Insert(group.Table).Default(gc.driver.Dialect())
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
return nil, rollback(tx, err)
}
id, err := res.LastInsertId()
if err != nil {
return nil, rollback(tx, err)
}
gr.ID = strconv.FormatInt(id, 10)
if err := tx.Commit(); err != nil {
return nil, err
}
return gr, nil
}
func (gc *GroupCreate) gremlinSave(ctx context.Context) (*Group, error) {
res := &gremlin.Response{}
query, bindings := gc.gremlin().Query()
if err := gc.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
if err, ok := isConstantError(res); ok {
return nil, err
}
gr := &Group{config: gc.config}
if err := gr.FromResponse(res); err != nil {
return nil, err
}
return gr, nil
}
func (gc *GroupCreate) gremlin() *dsl.Traversal {
v := g.AddV(group.Label)
return v.ValueMap(true)
}

View File

@@ -0,0 +1,88 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"fbc/ent/entc/integration/migrate/entv2/group"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// GroupDelete is the builder for deleting a Group entity.
type GroupDelete struct {
config
predicates []ent.Predicate
}
// Where adds a new predicate for the builder.
func (gd *GroupDelete) Where(ps ...ent.Predicate) *GroupDelete {
gd.predicates = append(gd.predicates, ps...)
return gd
}
// Exec executes the deletion query.
func (gd *GroupDelete) Exec(ctx context.Context) error {
switch gd.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gd.sqlExec(ctx)
case dialect.Neptune:
return gd.gremlinExec(ctx)
default:
return errors.New("entv2: unsupported dialect")
}
}
// ExecX is like Exec, but panics if an error occurs.
func (gd *GroupDelete) ExecX(ctx context.Context) {
if err := gd.Exec(ctx); err != nil {
panic(err)
}
}
func (gd *GroupDelete) sqlExec(ctx context.Context) error {
var res sql.Result
selector := sql.Select().From(sql.Table(group.Table))
for _, p := range gd.predicates {
p.SQL(selector)
}
query, args := sql.Delete(group.Table).FromSelect(selector).Query()
return gd.driver.Exec(ctx, query, args, &res)
}
func (gd *GroupDelete) gremlinExec(ctx context.Context) error {
res := &gremlin.Response{}
query, bindings := gd.gremlin().Query()
return gd.driver.Exec(ctx, query, bindings, res)
}
func (gd *GroupDelete) gremlin() *dsl.Traversal {
t := g.V().HasLabel(group.Label)
for _, p := range gd.predicates {
p.Gremlin(t)
}
return t.Drop()
}
// GroupDeleteOne is the builder for deleting a single Group entity.
type GroupDeleteOne struct {
gd *GroupDelete
}
// Exec executes the deletion query.
func (gdo *GroupDeleteOne) Exec(ctx context.Context) error {
return gdo.gd.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (gdo *GroupDeleteOne) ExecX(ctx context.Context) {
gdo.gd.ExecX(ctx)
}

View File

@@ -0,0 +1,603 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"fmt"
"math"
"fbc/ent/entc/integration/migrate/entv2/group"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/__"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// GroupQuery is the builder for querying Group entities.
type GroupQuery struct {
config
limit *int
offset *int
order []Order
unique []string
predicates []ent.Predicate
// intermediate queries.
sql *sql.Selector
gremlin *dsl.Traversal
}
// Where adds a new predicate for the builder.
func (gq *GroupQuery) Where(ps ...ent.Predicate) *GroupQuery {
gq.predicates = append(gq.predicates, ps...)
return gq
}
// Limit adds a limit step to the query.
func (gq *GroupQuery) Limit(limit int) *GroupQuery {
gq.limit = &limit
return gq
}
// Offset adds an offset step to the query.
func (gq *GroupQuery) Offset(offset int) *GroupQuery {
gq.offset = &offset
return gq
}
// Order adds an order step to the query.
func (gq *GroupQuery) Order(o ...Order) *GroupQuery {
gq.order = append(gq.order, o...)
return gq
}
// Get returns a Group entity by its id.
func (gq *GroupQuery) Get(ctx context.Context, id string) (*Group, error) {
return gq.Where(group.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (gq *GroupQuery) GetX(ctx context.Context, id string) *Group {
gr, err := gq.Get(ctx, id)
if err != nil {
panic(err)
}
return gr
}
// First returns the first Group entity in the query. Returns *ErrNotFound when no group was found.
func (gq *GroupQuery) First(ctx context.Context) (*Group, error) {
grs, err := gq.Limit(1).All(ctx)
if err != nil {
return nil, err
}
if len(grs) == 0 {
return nil, &ErrNotFound{group.Label}
}
return grs[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (gq *GroupQuery) FirstX(ctx context.Context) *Group {
gr, err := gq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return gr
}
// FirstID returns the first Group id in the query. Returns *ErrNotFound when no id was found.
func (gq *GroupQuery) FirstID(ctx context.Context) (id string, err error) {
var ids []string
if ids, err = gq.Limit(1).IDs(ctx); err != nil {
return
}
if len(ids) == 0 {
err = &ErrNotFound{group.Label}
return
}
return ids[0], nil
}
// FirstXID is like FirstID, but panics if an error occurs.
func (gq *GroupQuery) FirstXID(ctx context.Context) string {
id, err := gq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns the only Group entity in the query, returns an error if not exactly one entity was returned.
func (gq *GroupQuery) Only(ctx context.Context) (*Group, error) {
grs, err := gq.Limit(2).All(ctx)
if err != nil {
return nil, err
}
switch len(grs) {
case 1:
return grs[0], nil
case 0:
return nil, &ErrNotFound{group.Label}
default:
return nil, &ErrNotSingular{group.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (gq *GroupQuery) OnlyX(ctx context.Context) *Group {
gr, err := gq.Only(ctx)
if err != nil {
panic(err)
}
return gr
}
// OnlyID returns the only Group id in the query, returns an error if not exactly one id was returned.
func (gq *GroupQuery) OnlyID(ctx context.Context) (id string, err error) {
var ids []string
if ids, err = gq.Limit(2).IDs(ctx); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &ErrNotFound{group.Label}
default:
err = &ErrNotSingular{group.Label}
}
return
}
// OnlyXID is like OnlyID, but panics if an error occurs.
func (gq *GroupQuery) OnlyXID(ctx context.Context) string {
id, err := gq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Groups.
func (gq *GroupQuery) All(ctx context.Context) ([]*Group, error) {
switch gq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gq.sqlAll(ctx)
case dialect.Neptune:
return gq.gremlinAll(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// AllX is like All, but panics if an error occurs.
func (gq *GroupQuery) AllX(ctx context.Context) []*Group {
grs, err := gq.All(ctx)
if err != nil {
panic(err)
}
return grs
}
// IDs executes the query and returns a list of Group ids.
func (gq *GroupQuery) IDs(ctx context.Context) ([]string, error) {
switch gq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gq.sqlIDs(ctx)
case dialect.Neptune:
return gq.gremlinIDs(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// IDsX is like IDs, but panics if an error occurs.
func (gq *GroupQuery) IDsX(ctx context.Context) []string {
ids, err := gq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (gq *GroupQuery) Count(ctx context.Context) (int, error) {
switch gq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gq.sqlCount(ctx)
case dialect.Neptune:
return gq.gremlinCount(ctx)
default:
return 0, errors.New("entv2: unsupported dialect")
}
}
// CountX is like Count, but panics if an error occurs.
func (gq *GroupQuery) CountX(ctx context.Context) int {
count, err := gq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (gq *GroupQuery) Exist(ctx context.Context) (bool, error) {
switch gq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gq.sqlExist(ctx)
case dialect.Neptune:
return gq.gremlinExist(ctx)
default:
return false, errors.New("entv2: unsupported dialect")
}
}
// ExistX is like Exist, but panics if an error occurs.
func (gq *GroupQuery) ExistX(ctx context.Context) bool {
exist, err := gq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// GroupBy used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
func (gq *GroupQuery) GroupBy(field string, fields ...string) *GroupGroupBy {
group := &GroupGroupBy{config: gq.config}
group.fields = append([]string{field}, fields...)
switch gq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
group.sql = gq.sqlQuery()
case dialect.Neptune:
group.gremlin = gq.gremlinQuery()
}
return group
}
func (gq *GroupQuery) sqlAll(ctx context.Context) ([]*Group, error) {
rows := &sql.Rows{}
selector := gq.sqlQuery()
if unique := gq.unique; len(unique) == 0 {
selector.Distinct()
}
query, args := selector.Query()
if err := gq.driver.Query(ctx, query, args, rows); err != nil {
return nil, err
}
defer rows.Close()
var grs Groups
if err := grs.FromRows(rows); err != nil {
return nil, err
}
grs.config(gq.config)
return grs, nil
}
func (gq *GroupQuery) sqlCount(ctx context.Context) (int, error) {
rows := &sql.Rows{}
selector := gq.sqlQuery()
unique := []string{group.FieldID}
if len(gq.unique) > 0 {
unique = gq.unique
}
selector.Count(sql.Distinct(selector.Columns(unique...)...))
query, args := selector.Query()
if err := gq.driver.Query(ctx, query, args, rows); err != nil {
return 0, err
}
defer rows.Close()
if !rows.Next() {
return 0, errors.New("entv2: no rows found")
}
var n int
if err := rows.Scan(&n); err != nil {
return 0, fmt.Errorf("entv2: failed reading count: %v", err)
}
return n, nil
}
func (gq *GroupQuery) sqlExist(ctx context.Context) (bool, error) {
n, err := gq.sqlCount(ctx)
if err != nil {
return false, fmt.Errorf("entv2: check existence: %v", err)
}
return n > 0, nil
}
func (gq *GroupQuery) sqlIDs(ctx context.Context) ([]string, error) {
vs, err := gq.sqlAll(ctx)
if err != nil {
return nil, err
}
var ids []string
for _, v := range vs {
ids = append(ids, v.ID)
}
return ids, nil
}
func (gq *GroupQuery) sqlQuery() *sql.Selector {
t1 := sql.Table(group.Table)
selector := sql.Select(t1.Columns(group.Columns...)...).From(t1)
if gq.sql != nil {
selector = gq.sql
selector.Select(selector.Columns(group.Columns...)...)
}
for _, p := range gq.predicates {
p.SQL(selector)
}
for _, p := range gq.order {
p.SQL(selector)
}
if offset := gq.offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt64)
}
if limit := gq.limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
func (gq *GroupQuery) gremlinIDs(ctx context.Context) ([]string, error) {
res := &gremlin.Response{}
query, bindings := gq.gremlinQuery().Query()
if err := gq.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
vertices, err := res.ReadVertices()
if err != nil {
return nil, err
}
ids := make([]string, 0, len(vertices))
for _, vertex := range vertices {
ids = append(ids, vertex.ID.(string))
}
return ids, nil
}
func (gq *GroupQuery) gremlinAll(ctx context.Context) ([]*Group, error) {
res := &gremlin.Response{}
query, bindings := gq.gremlinQuery().ValueMap(true).Query()
if err := gq.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
var grs Groups
if err := grs.FromResponse(res); err != nil {
return nil, err
}
grs.config(gq.config)
return grs, nil
}
func (gq *GroupQuery) gremlinCount(ctx context.Context) (int, error) {
res := &gremlin.Response{}
query, bindings := gq.gremlinQuery().Count().Query()
if err := gq.driver.Exec(ctx, query, bindings, res); err != nil {
return 0, err
}
return res.ReadInt()
}
func (gq *GroupQuery) gremlinExist(ctx context.Context) (bool, error) {
res := &gremlin.Response{}
query, bindings := gq.gremlinQuery().HasNext().Query()
if err := gq.driver.Exec(ctx, query, bindings, res); err != nil {
return false, err
}
return res.ReadBool()
}
func (gq *GroupQuery) gremlinQuery() *dsl.Traversal {
v := g.V().HasLabel(group.Label)
if gq.gremlin != nil {
v = gq.gremlin.Clone()
}
for _, p := range gq.predicates {
p.Gremlin(v)
}
if len(gq.order) > 0 {
v.Order()
for _, p := range gq.order {
p.Gremlin(v)
}
}
switch limit, offset := gq.limit, gq.offset; {
case limit != nil && offset != nil:
v.Range(*offset, *offset+*limit)
case offset != nil:
v.Range(*offset, math.MaxInt64)
case limit != nil:
v.Limit(*limit)
}
if unique := gq.unique; len(unique) == 0 {
v.Dedup()
}
return v
}
// GroupQuery is the builder for group-by Group entities.
type GroupGroupBy struct {
config
fields []string
fns []Aggregate
// intermediate queries.
sql *sql.Selector
gremlin *dsl.Traversal
}
// Aggregate adds the given aggregation functions to the group-by query.
func (ggb *GroupGroupBy) Aggregate(fns ...Aggregate) *GroupGroupBy {
ggb.fns = append(ggb.fns, fns...)
return ggb
}
// Scan applies the group-by query and scan the result into the given value.
func (ggb *GroupGroupBy) Scan(ctx context.Context, v interface{}) error {
switch ggb.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return ggb.sqlScan(ctx, v)
case dialect.Neptune:
return ggb.gremlinScan(ctx, v)
default:
return errors.New("ggb: unsupported dialect")
}
}
// ScanX is like Scan, but panics if an error occurs.
func (ggb *GroupGroupBy) ScanX(ctx context.Context, v interface{}) {
if err := ggb.Scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from group-by. It is only allowed when querying group-by with one field.
func (ggb *GroupGroupBy) Strings(ctx context.Context) ([]string, error) {
if len(ggb.fields) > 1 {
return nil, errors.New("entv2: GroupGroupBy.Strings is not achievable when grouping more than 1 field")
}
var v []string
if err := ggb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (ggb *GroupGroupBy) StringsX(ctx context.Context) []string {
v, err := ggb.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from group-by. It is only allowed when querying group-by with one field.
func (ggb *GroupGroupBy) Ints(ctx context.Context) ([]int, error) {
if len(ggb.fields) > 1 {
return nil, errors.New("entv2: GroupGroupBy.Ints is not achievable when grouping more than 1 field")
}
var v []int
if err := ggb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (ggb *GroupGroupBy) IntsX(ctx context.Context) []int {
v, err := ggb.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from group-by. It is only allowed when querying group-by with one field.
func (ggb *GroupGroupBy) Float64s(ctx context.Context) ([]float64, error) {
if len(ggb.fields) > 1 {
return nil, errors.New("entv2: GroupGroupBy.Float64s is not achievable when grouping more than 1 field")
}
var v []float64
if err := ggb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (ggb *GroupGroupBy) Float64sX(ctx context.Context) []float64 {
v, err := ggb.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from group-by. It is only allowed when querying group-by with one field.
func (ggb *GroupGroupBy) Bools(ctx context.Context) ([]bool, error) {
if len(ggb.fields) > 1 {
return nil, errors.New("entv2: GroupGroupBy.Bools is not achievable when grouping more than 1 field")
}
var v []bool
if err := ggb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (ggb *GroupGroupBy) BoolsX(ctx context.Context) []bool {
v, err := ggb.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
func (ggb *GroupGroupBy) sqlScan(ctx context.Context, v interface{}) error {
rows := &sql.Rows{}
query, args := ggb.sqlQuery().Query()
if err := ggb.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
func (ggb *GroupGroupBy) sqlQuery() *sql.Selector {
selector := ggb.sql
columns := make([]string, 0, len(ggb.fields)+len(ggb.fns))
columns = append(columns, ggb.fields...)
for _, fn := range ggb.fns {
columns = append(columns, fn.SQL(selector))
}
return selector.Select(columns...).GroupBy(ggb.fields...)
}
func (ggb *GroupGroupBy) gremlinScan(ctx context.Context, v interface{}) error {
res := &gremlin.Response{}
query, bindings := ggb.gremlinQuery().Query()
if err := ggb.driver.Exec(ctx, query, bindings, res); err != nil {
return err
}
if len(ggb.fields)+len(ggb.fns) == 1 {
return res.ReadVal(v)
}
vm, err := res.ReadValueMap()
if err != nil {
return err
}
return vm.Decode(v)
}
func (ggb *GroupGroupBy) gremlinQuery() *dsl.Traversal {
var (
trs []interface{}
names []interface{}
)
for _, fn := range ggb.fns {
name, tr := fn.Gremlin("p", "")
trs = append(trs, tr)
names = append(names, name)
}
for _, f := range ggb.fields {
names = append(names, f)
trs = append(trs, __.As("p").Unfold().Values(f).As(f))
}
return ggb.gremlin.Group().
By(__.Values(ggb.fields...).Fold()).
By(__.Fold().Match(trs...).Select(names...)).
Select(dsl.Values).
Next()
}

View File

@@ -0,0 +1,231 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"fmt"
"fbc/ent/entc/integration/migrate/entv2/group"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// GroupUpdate is the builder for updating Group entities.
type GroupUpdate struct {
config
predicates []ent.Predicate
}
// Where adds a new predicate for the builder.
func (gu *GroupUpdate) Where(ps ...ent.Predicate) *GroupUpdate {
gu.predicates = append(gu.predicates, ps...)
return gu
}
// Save executes the query and returns the number of rows/vertices matched by this operation.
func (gu *GroupUpdate) Save(ctx context.Context) (int, error) {
switch gu.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return gu.sqlSave(ctx)
case dialect.Neptune:
vertices, err := gu.gremlinSave(ctx)
return len(vertices), err
default:
return 0, errors.New("entv2: unsupported dialect")
}
}
// SaveX is like Save, but panics if an error occurs.
func (gu *GroupUpdate) SaveX(ctx context.Context) int {
affected, err := gu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (gu *GroupUpdate) Exec(ctx context.Context) error {
_, err := gu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (gu *GroupUpdate) ExecX(ctx context.Context) {
if err := gu.Exec(ctx); err != nil {
panic(err)
}
}
func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
selector := sql.Select(group.FieldID).From(sql.Table(group.Table))
for _, p := range gu.predicates {
p.SQL(selector)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err = gu.driver.Query(ctx, query, args, rows); err != nil {
return 0, err
}
defer rows.Close()
var ids []int
for rows.Next() {
var id int
if err := rows.Scan(&id); err != nil {
return 0, fmt.Errorf("entv2: failed reading id: %v", err)
}
ids = append(ids, id)
}
if len(ids) == 0 {
return 0, nil
}
tx, err := gu.driver.Tx(ctx)
if err != nil {
return 0, err
}
if err = tx.Commit(); err != nil {
return 0, err
}
return len(ids), nil
}
func (gu *GroupUpdate) gremlinSave(ctx context.Context) ([]*Group, error) {
res := &gremlin.Response{}
query, bindings := gu.gremlin().Query()
if err := gu.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
if err, ok := isConstantError(res); ok {
return nil, err
}
var grs Groups
grs.config(gu.config)
if err := grs.FromResponse(res); err != nil {
return nil, err
}
return grs, nil
}
func (gu *GroupUpdate) gremlin() *dsl.Traversal {
v := g.V().HasLabel(group.Label)
for _, p := range gu.predicates {
p.Gremlin(v)
}
var (
trs []*dsl.Traversal
)
v.ValueMap(true)
trs = append(trs, v)
return dsl.Join(trs...)
}
// GroupUpdateOne is the builder for updating a single Group entity.
type GroupUpdateOne struct {
config
id string
}
// Save executes the query and returns the updated entity.
func (guo *GroupUpdateOne) Save(ctx context.Context) (*Group, error) {
switch guo.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return guo.sqlSave(ctx)
case dialect.Neptune:
return guo.gremlinSave(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// SaveX is like Save, but panics if an error occurs.
func (guo *GroupUpdateOne) SaveX(ctx context.Context) *Group {
gr, err := guo.Save(ctx)
if err != nil {
panic(err)
}
return gr
}
// Exec executes the query on the entity.
func (guo *GroupUpdateOne) Exec(ctx context.Context) error {
_, err := guo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (guo *GroupUpdateOne) ExecX(ctx context.Context) {
if err := guo.Exec(ctx); err != nil {
panic(err)
}
}
func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) {
selector := sql.Select(group.Columns...).From(sql.Table(group.Table))
group.ID(guo.id).SQL(selector)
rows := &sql.Rows{}
query, args := selector.Query()
if err = guo.driver.Query(ctx, query, args, rows); err != nil {
return nil, err
}
defer rows.Close()
var ids []int
for rows.Next() {
var id int
gr = &Group{config: guo.config}
if err := gr.FromRows(rows); err != nil {
return nil, fmt.Errorf("entv2: failed scanning row into Group: %v", err)
}
id = gr.id()
ids = append(ids, id)
}
switch n := len(ids); {
case n == 0:
return nil, fmt.Errorf("entv2: Group not found with id: %v", guo.id)
case n > 1:
return nil, fmt.Errorf("entv2: more than one Group with the same id: %v", guo.id)
}
tx, err := guo.driver.Tx(ctx)
if err != nil {
return nil, err
}
if err = tx.Commit(); err != nil {
return nil, err
}
return gr, nil
}
func (guo *GroupUpdateOne) gremlinSave(ctx context.Context) (*Group, error) {
res := &gremlin.Response{}
query, bindings := guo.gremlin(guo.id).Query()
if err := guo.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
if err, ok := isConstantError(res); ok {
return nil, err
}
gr := &Group{config: guo.config}
if err := gr.FromResponse(res); err != nil {
return nil, err
}
return gr, nil
}
func (guo *GroupUpdateOne) gremlin(id string) *dsl.Traversal {
v := g.V(id)
var (
trs []*dsl.Traversal
)
v.ValueMap(true)
trs = append(trs, v)
return dsl.Join(trs...)
}

View File

@@ -3,31 +3,27 @@
package migrate
import (
"context"
"fmt"
"fbc/ent/dialect"
"fbc/ent/dialect/sql/schema"
"fbc/ent/field"
)
var (
nullable = true
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "age", Type: field.TypeInt},
{Name: "name", Type: field.TypeString, Size: 2147483647},
{Name: "phone", Type: field.TypeString},
}
// UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{
Name: "users",
Columns: UsersColumns,
PrimaryKey: []*schema.Column{UsersColumns[0]},
ForeignKeys: []*schema.ForeignKey{},
}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
UsersTable,
}
)
func init() {
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv dialect.Driver
universalID bool
}
// NewSchema creates a new schema client.
func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
// Create creates all schema resources.
func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
migrate, err := schema.NewMigrate(s.drv, opts...)
if err != nil {
return fmt.Errorf("ent/migrate: %v", err)
}
return migrate.Create(ctx, Tables...)
}

View File

@@ -3,39 +3,55 @@
package migrate
import (
"context"
"fmt"
"fbc/ent/dialect"
"fbc/ent/dialect/sql/schema"
"fbc/ent/field"
)
// SQLDialect wraps the dialect.Driver with additional migration methods.
type SQLDriver interface {
Create(context.Context, ...*schema.Table) error
}
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv SQLDriver
}
// NewSchema creates a new schema client.
func NewSchema(drv dialect.Driver) *Schema {
s := &Schema{}
switch drv.Dialect() {
case dialect.MySQL:
s.drv = &schema.MySQL{Driver: drv}
case dialect.SQLite:
s.drv = &schema.SQLite{Driver: drv}
var (
nullable = true
// GroupsColumns holds the columns for the "groups" table.
GroupsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
}
return s
}
// Create creates all schema resources.
func (s *Schema) Create(ctx context.Context) error {
if s.drv == nil {
return fmt.Errorf("entv2/migrate: dialect does not support migration")
// GroupsTable holds the schema information for the "groups" table.
GroupsTable = &schema.Table{
Name: "groups",
Columns: GroupsColumns,
PrimaryKey: []*schema.Column{GroupsColumns[0]},
ForeignKeys: []*schema.ForeignKey{},
}
return s.drv.Create(ctx, Tables...)
// PetsColumns holds the columns for the "pets" table.
PetsColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
}
// PetsTable holds the schema information for the "pets" table.
PetsTable = &schema.Table{
Name: "pets",
Columns: PetsColumns,
PrimaryKey: []*schema.Column{PetsColumns[0]},
ForeignKeys: []*schema.ForeignKey{},
}
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "age", Type: field.TypeInt},
{Name: "name", Type: field.TypeString, Size: 2147483647},
{Name: "phone", Type: field.TypeString},
}
// UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{
Name: "users",
Columns: UsersColumns,
PrimaryKey: []*schema.Column{UsersColumns[0]},
ForeignKeys: []*schema.ForeignKey{},
}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
GroupsTable,
PetsTable,
UsersTable,
}
)
func init() {
}

View File

@@ -0,0 +1,125 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"bytes"
"fmt"
"strconv"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
)
// Pet is the model entity for the Pet schema.
type Pet struct {
config
// ID of the ent.
ID string `json:"id,omitempty"`
}
// FromResponse scans the gremlin response data into Pet.
func (pe *Pet) FromResponse(res *gremlin.Response) error {
vmap, err := res.ReadValueMap()
if err != nil {
return err
}
var vpe struct {
ID string `json:"id,omitempty"`
}
if err := vmap.Decode(&vpe); err != nil {
return err
}
pe.ID = vpe.ID
return nil
}
// FromRows scans the sql response data into Pet.
func (pe *Pet) FromRows(rows *sql.Rows) error {
var vpe struct {
ID int
}
// the order here should be the same as in the `pet.Columns`.
if err := rows.Scan(
&vpe.ID,
); err != nil {
return err
}
pe.ID = strconv.Itoa(vpe.ID)
return nil
}
// Update returns a builder for updating this Pet.
// Note that, you need to call Pet.Unwrap() before calling this method, if this Pet
// was returned from a transaction, and the transaction was committed or rolled back.
func (pe *Pet) Update() *PetUpdateOne {
return (&PetClient{pe.config}).UpdateOne(pe)
}
// Unwrap unwraps the entity that was returned from a transaction after it was closed,
// so that all next queries will be executed through the driver which created the transaction.
func (pe *Pet) Unwrap() *Pet {
tx, ok := pe.config.driver.(*txDriver)
if !ok {
panic("entv2: Pet is not a transactional entity")
}
pe.config.driver = tx.drv
return pe
}
// String implements the fmt.Stringer.
func (pe *Pet) String() string {
buf := bytes.NewBuffer(nil)
buf.WriteString("Pet(")
buf.WriteString(fmt.Sprintf("id=%v", pe.ID))
buf.WriteString(")")
return buf.String()
}
// id returns the int representation of the ID field.
func (pe *Pet) id() int {
id, _ := strconv.Atoi(pe.ID)
return id
}
// Pets is a parsable slice of Pet.
type Pets []*Pet
// FromResponse scans the gremlin response data into Pets.
func (pe *Pets) FromResponse(res *gremlin.Response) error {
vmap, err := res.ReadValueMap()
if err != nil {
return err
}
var vpe []struct {
ID string `json:"id,omitempty"`
}
if err := vmap.Decode(&vpe); err != nil {
return err
}
for _, v := range vpe {
*pe = append(*pe, &Pet{
ID: v.ID,
})
}
return nil
}
// FromRows scans the sql response data into Pets.
func (pe *Pets) FromRows(rows *sql.Rows) error {
for rows.Next() {
vpe := &Pet{}
if err := vpe.FromRows(rows); err != nil {
return err
}
*pe = append(*pe, vpe)
}
return nil
}
func (pe Pets) config(cfg config) {
for i := range pe {
pe[i].config = cfg
}
}

View File

@@ -0,0 +1,17 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package pet
const (
// Label holds the string label denoting the pet type in the database.
Label = "pet"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// Table holds the table name of the pet in the database.
Table = "pets"
)
// Columns holds all SQL columns are pet fields.
var Columns = []string{
FieldID,
}

View File

@@ -0,0 +1,156 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package pet
import (
"strconv"
"fbc/ent"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/p"
)
// ID filters vertices based on their identifier.
func ID(id string) ent.Predicate {
return ent.Predicate{
SQL: func(s *sql.Selector) {
id, _ := strconv.Atoi(id)
s.Where(sql.EQ(s.C(FieldID), id))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.EQ(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.NEQ(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.GT(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.GTE(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.LT(s.C(FieldID), v))
},
Gremlin: 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) {
v, _ := strconv.Atoi(id)
s.Where(sql.LTE(s.C(FieldID), v))
},
Gremlin: 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) {
// 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 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i], _ = strconv.Atoi(ids[i])
}
s.Where(sql.In(s.C(FieldID), v...))
},
Gremlin: 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) {
// 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 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i], _ = strconv.Atoi(ids[i])
}
s.Where(sql.NotIn(s.C(FieldID), v...))
},
Gremlin: func(t *dsl.Traversal) {
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
t.HasID(p.Without(v...))
},
}
}

View File

@@ -0,0 +1,90 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"strconv"
"fbc/ent/entc/integration/migrate/entv2/pet"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// PetCreate is the builder for creating a Pet entity.
type PetCreate struct {
config
}
// Save creates the Pet in the database.
func (pc *PetCreate) Save(ctx context.Context) (*Pet, error) {
switch pc.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pc.sqlSave(ctx)
case dialect.Neptune:
return pc.gremlinSave(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// SaveX calls Save and panics if Save returns an error.
func (pc *PetCreate) SaveX(ctx context.Context) *Pet {
v, err := pc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
func (pc *PetCreate) sqlSave(ctx context.Context) (*Pet, error) {
var (
res sql.Result
pe = &Pet{config: pc.config}
)
tx, err := pc.driver.Tx(ctx)
if err != nil {
return nil, err
}
builder := sql.Insert(pet.Table).Default(pc.driver.Dialect())
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
return nil, rollback(tx, err)
}
id, err := res.LastInsertId()
if err != nil {
return nil, rollback(tx, err)
}
pe.ID = strconv.FormatInt(id, 10)
if err := tx.Commit(); err != nil {
return nil, err
}
return pe, nil
}
func (pc *PetCreate) gremlinSave(ctx context.Context) (*Pet, error) {
res := &gremlin.Response{}
query, bindings := pc.gremlin().Query()
if err := pc.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
if err, ok := isConstantError(res); ok {
return nil, err
}
pe := &Pet{config: pc.config}
if err := pe.FromResponse(res); err != nil {
return nil, err
}
return pe, nil
}
func (pc *PetCreate) gremlin() *dsl.Traversal {
v := g.AddV(pet.Label)
return v.ValueMap(true)
}

View File

@@ -0,0 +1,88 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"fbc/ent/entc/integration/migrate/entv2/pet"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// PetDelete is the builder for deleting a Pet entity.
type PetDelete struct {
config
predicates []ent.Predicate
}
// Where adds a new predicate for the builder.
func (pd *PetDelete) Where(ps ...ent.Predicate) *PetDelete {
pd.predicates = append(pd.predicates, ps...)
return pd
}
// Exec executes the deletion query.
func (pd *PetDelete) Exec(ctx context.Context) error {
switch pd.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pd.sqlExec(ctx)
case dialect.Neptune:
return pd.gremlinExec(ctx)
default:
return errors.New("entv2: unsupported dialect")
}
}
// ExecX is like Exec, but panics if an error occurs.
func (pd *PetDelete) ExecX(ctx context.Context) {
if err := pd.Exec(ctx); err != nil {
panic(err)
}
}
func (pd *PetDelete) sqlExec(ctx context.Context) error {
var res sql.Result
selector := sql.Select().From(sql.Table(pet.Table))
for _, p := range pd.predicates {
p.SQL(selector)
}
query, args := sql.Delete(pet.Table).FromSelect(selector).Query()
return pd.driver.Exec(ctx, query, args, &res)
}
func (pd *PetDelete) gremlinExec(ctx context.Context) error {
res := &gremlin.Response{}
query, bindings := pd.gremlin().Query()
return pd.driver.Exec(ctx, query, bindings, res)
}
func (pd *PetDelete) gremlin() *dsl.Traversal {
t := g.V().HasLabel(pet.Label)
for _, p := range pd.predicates {
p.Gremlin(t)
}
return t.Drop()
}
// PetDeleteOne is the builder for deleting a single Pet entity.
type PetDeleteOne struct {
pd *PetDelete
}
// Exec executes the deletion query.
func (pdo *PetDeleteOne) Exec(ctx context.Context) error {
return pdo.pd.Exec(ctx)
}
// ExecX is like Exec, but panics if an error occurs.
func (pdo *PetDeleteOne) ExecX(ctx context.Context) {
pdo.pd.ExecX(ctx)
}

View File

@@ -0,0 +1,603 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"fmt"
"math"
"fbc/ent/entc/integration/migrate/entv2/pet"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/__"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// PetQuery is the builder for querying Pet entities.
type PetQuery struct {
config
limit *int
offset *int
order []Order
unique []string
predicates []ent.Predicate
// intermediate queries.
sql *sql.Selector
gremlin *dsl.Traversal
}
// Where adds a new predicate for the builder.
func (pq *PetQuery) Where(ps ...ent.Predicate) *PetQuery {
pq.predicates = append(pq.predicates, ps...)
return pq
}
// Limit adds a limit step to the query.
func (pq *PetQuery) Limit(limit int) *PetQuery {
pq.limit = &limit
return pq
}
// Offset adds an offset step to the query.
func (pq *PetQuery) Offset(offset int) *PetQuery {
pq.offset = &offset
return pq
}
// Order adds an order step to the query.
func (pq *PetQuery) Order(o ...Order) *PetQuery {
pq.order = append(pq.order, o...)
return pq
}
// Get returns a Pet entity by its id.
func (pq *PetQuery) Get(ctx context.Context, id string) (*Pet, error) {
return pq.Where(pet.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (pq *PetQuery) GetX(ctx context.Context, id string) *Pet {
pe, err := pq.Get(ctx, id)
if err != nil {
panic(err)
}
return pe
}
// First returns the first Pet entity in the query. Returns *ErrNotFound when no pet was found.
func (pq *PetQuery) First(ctx context.Context) (*Pet, error) {
pes, err := pq.Limit(1).All(ctx)
if err != nil {
return nil, err
}
if len(pes) == 0 {
return nil, &ErrNotFound{pet.Label}
}
return pes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (pq *PetQuery) FirstX(ctx context.Context) *Pet {
pe, err := pq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return pe
}
// FirstID returns the first Pet id in the query. Returns *ErrNotFound when no id was found.
func (pq *PetQuery) FirstID(ctx context.Context) (id string, err error) {
var ids []string
if ids, err = pq.Limit(1).IDs(ctx); err != nil {
return
}
if len(ids) == 0 {
err = &ErrNotFound{pet.Label}
return
}
return ids[0], nil
}
// FirstXID is like FirstID, but panics if an error occurs.
func (pq *PetQuery) FirstXID(ctx context.Context) string {
id, err := pq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns the only Pet entity in the query, returns an error if not exactly one entity was returned.
func (pq *PetQuery) Only(ctx context.Context) (*Pet, error) {
pes, err := pq.Limit(2).All(ctx)
if err != nil {
return nil, err
}
switch len(pes) {
case 1:
return pes[0], nil
case 0:
return nil, &ErrNotFound{pet.Label}
default:
return nil, &ErrNotSingular{pet.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (pq *PetQuery) OnlyX(ctx context.Context) *Pet {
pe, err := pq.Only(ctx)
if err != nil {
panic(err)
}
return pe
}
// OnlyID returns the only Pet id in the query, returns an error if not exactly one id was returned.
func (pq *PetQuery) OnlyID(ctx context.Context) (id string, err error) {
var ids []string
if ids, err = pq.Limit(2).IDs(ctx); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &ErrNotFound{pet.Label}
default:
err = &ErrNotSingular{pet.Label}
}
return
}
// OnlyXID is like OnlyID, but panics if an error occurs.
func (pq *PetQuery) OnlyXID(ctx context.Context) string {
id, err := pq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Pets.
func (pq *PetQuery) All(ctx context.Context) ([]*Pet, error) {
switch pq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pq.sqlAll(ctx)
case dialect.Neptune:
return pq.gremlinAll(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// AllX is like All, but panics if an error occurs.
func (pq *PetQuery) AllX(ctx context.Context) []*Pet {
pes, err := pq.All(ctx)
if err != nil {
panic(err)
}
return pes
}
// IDs executes the query and returns a list of Pet ids.
func (pq *PetQuery) IDs(ctx context.Context) ([]string, error) {
switch pq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pq.sqlIDs(ctx)
case dialect.Neptune:
return pq.gremlinIDs(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// IDsX is like IDs, but panics if an error occurs.
func (pq *PetQuery) IDsX(ctx context.Context) []string {
ids, err := pq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (pq *PetQuery) Count(ctx context.Context) (int, error) {
switch pq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pq.sqlCount(ctx)
case dialect.Neptune:
return pq.gremlinCount(ctx)
default:
return 0, errors.New("entv2: unsupported dialect")
}
}
// CountX is like Count, but panics if an error occurs.
func (pq *PetQuery) CountX(ctx context.Context) int {
count, err := pq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (pq *PetQuery) Exist(ctx context.Context) (bool, error) {
switch pq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pq.sqlExist(ctx)
case dialect.Neptune:
return pq.gremlinExist(ctx)
default:
return false, errors.New("entv2: unsupported dialect")
}
}
// ExistX is like Exist, but panics if an error occurs.
func (pq *PetQuery) ExistX(ctx context.Context) bool {
exist, err := pq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// GroupBy used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
func (pq *PetQuery) GroupBy(field string, fields ...string) *PetGroupBy {
group := &PetGroupBy{config: pq.config}
group.fields = append([]string{field}, fields...)
switch pq.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
group.sql = pq.sqlQuery()
case dialect.Neptune:
group.gremlin = pq.gremlinQuery()
}
return group
}
func (pq *PetQuery) sqlAll(ctx context.Context) ([]*Pet, error) {
rows := &sql.Rows{}
selector := pq.sqlQuery()
if unique := pq.unique; len(unique) == 0 {
selector.Distinct()
}
query, args := selector.Query()
if err := pq.driver.Query(ctx, query, args, rows); err != nil {
return nil, err
}
defer rows.Close()
var pes Pets
if err := pes.FromRows(rows); err != nil {
return nil, err
}
pes.config(pq.config)
return pes, nil
}
func (pq *PetQuery) sqlCount(ctx context.Context) (int, error) {
rows := &sql.Rows{}
selector := pq.sqlQuery()
unique := []string{pet.FieldID}
if len(pq.unique) > 0 {
unique = pq.unique
}
selector.Count(sql.Distinct(selector.Columns(unique...)...))
query, args := selector.Query()
if err := pq.driver.Query(ctx, query, args, rows); err != nil {
return 0, err
}
defer rows.Close()
if !rows.Next() {
return 0, errors.New("entv2: no rows found")
}
var n int
if err := rows.Scan(&n); err != nil {
return 0, fmt.Errorf("entv2: failed reading count: %v", err)
}
return n, nil
}
func (pq *PetQuery) sqlExist(ctx context.Context) (bool, error) {
n, err := pq.sqlCount(ctx)
if err != nil {
return false, fmt.Errorf("entv2: check existence: %v", err)
}
return n > 0, nil
}
func (pq *PetQuery) sqlIDs(ctx context.Context) ([]string, error) {
vs, err := pq.sqlAll(ctx)
if err != nil {
return nil, err
}
var ids []string
for _, v := range vs {
ids = append(ids, v.ID)
}
return ids, nil
}
func (pq *PetQuery) sqlQuery() *sql.Selector {
t1 := sql.Table(pet.Table)
selector := sql.Select(t1.Columns(pet.Columns...)...).From(t1)
if pq.sql != nil {
selector = pq.sql
selector.Select(selector.Columns(pet.Columns...)...)
}
for _, p := range pq.predicates {
p.SQL(selector)
}
for _, p := range pq.order {
p.SQL(selector)
}
if offset := pq.offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt64)
}
if limit := pq.limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
func (pq *PetQuery) gremlinIDs(ctx context.Context) ([]string, error) {
res := &gremlin.Response{}
query, bindings := pq.gremlinQuery().Query()
if err := pq.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
vertices, err := res.ReadVertices()
if err != nil {
return nil, err
}
ids := make([]string, 0, len(vertices))
for _, vertex := range vertices {
ids = append(ids, vertex.ID.(string))
}
return ids, nil
}
func (pq *PetQuery) gremlinAll(ctx context.Context) ([]*Pet, error) {
res := &gremlin.Response{}
query, bindings := pq.gremlinQuery().ValueMap(true).Query()
if err := pq.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
var pes Pets
if err := pes.FromResponse(res); err != nil {
return nil, err
}
pes.config(pq.config)
return pes, nil
}
func (pq *PetQuery) gremlinCount(ctx context.Context) (int, error) {
res := &gremlin.Response{}
query, bindings := pq.gremlinQuery().Count().Query()
if err := pq.driver.Exec(ctx, query, bindings, res); err != nil {
return 0, err
}
return res.ReadInt()
}
func (pq *PetQuery) gremlinExist(ctx context.Context) (bool, error) {
res := &gremlin.Response{}
query, bindings := pq.gremlinQuery().HasNext().Query()
if err := pq.driver.Exec(ctx, query, bindings, res); err != nil {
return false, err
}
return res.ReadBool()
}
func (pq *PetQuery) gremlinQuery() *dsl.Traversal {
v := g.V().HasLabel(pet.Label)
if pq.gremlin != nil {
v = pq.gremlin.Clone()
}
for _, p := range pq.predicates {
p.Gremlin(v)
}
if len(pq.order) > 0 {
v.Order()
for _, p := range pq.order {
p.Gremlin(v)
}
}
switch limit, offset := pq.limit, pq.offset; {
case limit != nil && offset != nil:
v.Range(*offset, *offset+*limit)
case offset != nil:
v.Range(*offset, math.MaxInt64)
case limit != nil:
v.Limit(*limit)
}
if unique := pq.unique; len(unique) == 0 {
v.Dedup()
}
return v
}
// PetQuery is the builder for group-by Pet entities.
type PetGroupBy struct {
config
fields []string
fns []Aggregate
// intermediate queries.
sql *sql.Selector
gremlin *dsl.Traversal
}
// Aggregate adds the given aggregation functions to the group-by query.
func (pgb *PetGroupBy) Aggregate(fns ...Aggregate) *PetGroupBy {
pgb.fns = append(pgb.fns, fns...)
return pgb
}
// Scan applies the group-by query and scan the result into the given value.
func (pgb *PetGroupBy) Scan(ctx context.Context, v interface{}) error {
switch pgb.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pgb.sqlScan(ctx, v)
case dialect.Neptune:
return pgb.gremlinScan(ctx, v)
default:
return errors.New("pgb: unsupported dialect")
}
}
// ScanX is like Scan, but panics if an error occurs.
func (pgb *PetGroupBy) ScanX(ctx context.Context, v interface{}) {
if err := pgb.Scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from group-by. It is only allowed when querying group-by with one field.
func (pgb *PetGroupBy) Strings(ctx context.Context) ([]string, error) {
if len(pgb.fields) > 1 {
return nil, errors.New("entv2: PetGroupBy.Strings is not achievable when grouping more than 1 field")
}
var v []string
if err := pgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (pgb *PetGroupBy) StringsX(ctx context.Context) []string {
v, err := pgb.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from group-by. It is only allowed when querying group-by with one field.
func (pgb *PetGroupBy) Ints(ctx context.Context) ([]int, error) {
if len(pgb.fields) > 1 {
return nil, errors.New("entv2: PetGroupBy.Ints is not achievable when grouping more than 1 field")
}
var v []int
if err := pgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (pgb *PetGroupBy) IntsX(ctx context.Context) []int {
v, err := pgb.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from group-by. It is only allowed when querying group-by with one field.
func (pgb *PetGroupBy) Float64s(ctx context.Context) ([]float64, error) {
if len(pgb.fields) > 1 {
return nil, errors.New("entv2: PetGroupBy.Float64s is not achievable when grouping more than 1 field")
}
var v []float64
if err := pgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (pgb *PetGroupBy) Float64sX(ctx context.Context) []float64 {
v, err := pgb.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from group-by. It is only allowed when querying group-by with one field.
func (pgb *PetGroupBy) Bools(ctx context.Context) ([]bool, error) {
if len(pgb.fields) > 1 {
return nil, errors.New("entv2: PetGroupBy.Bools is not achievable when grouping more than 1 field")
}
var v []bool
if err := pgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (pgb *PetGroupBy) BoolsX(ctx context.Context) []bool {
v, err := pgb.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
func (pgb *PetGroupBy) sqlScan(ctx context.Context, v interface{}) error {
rows := &sql.Rows{}
query, args := pgb.sqlQuery().Query()
if err := pgb.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
func (pgb *PetGroupBy) sqlQuery() *sql.Selector {
selector := pgb.sql
columns := make([]string, 0, len(pgb.fields)+len(pgb.fns))
columns = append(columns, pgb.fields...)
for _, fn := range pgb.fns {
columns = append(columns, fn.SQL(selector))
}
return selector.Select(columns...).GroupBy(pgb.fields...)
}
func (pgb *PetGroupBy) gremlinScan(ctx context.Context, v interface{}) error {
res := &gremlin.Response{}
query, bindings := pgb.gremlinQuery().Query()
if err := pgb.driver.Exec(ctx, query, bindings, res); err != nil {
return err
}
if len(pgb.fields)+len(pgb.fns) == 1 {
return res.ReadVal(v)
}
vm, err := res.ReadValueMap()
if err != nil {
return err
}
return vm.Decode(v)
}
func (pgb *PetGroupBy) gremlinQuery() *dsl.Traversal {
var (
trs []interface{}
names []interface{}
)
for _, fn := range pgb.fns {
name, tr := fn.Gremlin("p", "")
trs = append(trs, tr)
names = append(names, name)
}
for _, f := range pgb.fields {
names = append(names, f)
trs = append(trs, __.As("p").Unfold().Values(f).As(f))
}
return pgb.gremlin.Group().
By(__.Values(pgb.fields...).Fold()).
By(__.Fold().Match(trs...).Select(names...)).
Select(dsl.Values).
Next()
}

View File

@@ -0,0 +1,231 @@
// Code generated (@generated) by entc, DO NOT EDIT.
package entv2
import (
"context"
"errors"
"fmt"
"fbc/ent/entc/integration/migrate/entv2/pet"
"fbc/ent"
"fbc/ent/dialect"
"fbc/ent/dialect/sql"
"fbc/lib/go/gremlin"
"fbc/lib/go/gremlin/graph/dsl"
"fbc/lib/go/gremlin/graph/dsl/g"
)
// PetUpdate is the builder for updating Pet entities.
type PetUpdate struct {
config
predicates []ent.Predicate
}
// Where adds a new predicate for the builder.
func (pu *PetUpdate) Where(ps ...ent.Predicate) *PetUpdate {
pu.predicates = append(pu.predicates, ps...)
return pu
}
// Save executes the query and returns the number of rows/vertices matched by this operation.
func (pu *PetUpdate) Save(ctx context.Context) (int, error) {
switch pu.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return pu.sqlSave(ctx)
case dialect.Neptune:
vertices, err := pu.gremlinSave(ctx)
return len(vertices), err
default:
return 0, errors.New("entv2: unsupported dialect")
}
}
// SaveX is like Save, but panics if an error occurs.
func (pu *PetUpdate) SaveX(ctx context.Context) int {
affected, err := pu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (pu *PetUpdate) Exec(ctx context.Context) error {
_, err := pu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (pu *PetUpdate) ExecX(ctx context.Context) {
if err := pu.Exec(ctx); err != nil {
panic(err)
}
}
func (pu *PetUpdate) sqlSave(ctx context.Context) (n int, err error) {
selector := sql.Select(pet.FieldID).From(sql.Table(pet.Table))
for _, p := range pu.predicates {
p.SQL(selector)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err = pu.driver.Query(ctx, query, args, rows); err != nil {
return 0, err
}
defer rows.Close()
var ids []int
for rows.Next() {
var id int
if err := rows.Scan(&id); err != nil {
return 0, fmt.Errorf("entv2: failed reading id: %v", err)
}
ids = append(ids, id)
}
if len(ids) == 0 {
return 0, nil
}
tx, err := pu.driver.Tx(ctx)
if err != nil {
return 0, err
}
if err = tx.Commit(); err != nil {
return 0, err
}
return len(ids), nil
}
func (pu *PetUpdate) gremlinSave(ctx context.Context) ([]*Pet, error) {
res := &gremlin.Response{}
query, bindings := pu.gremlin().Query()
if err := pu.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
if err, ok := isConstantError(res); ok {
return nil, err
}
var pes Pets
pes.config(pu.config)
if err := pes.FromResponse(res); err != nil {
return nil, err
}
return pes, nil
}
func (pu *PetUpdate) gremlin() *dsl.Traversal {
v := g.V().HasLabel(pet.Label)
for _, p := range pu.predicates {
p.Gremlin(v)
}
var (
trs []*dsl.Traversal
)
v.ValueMap(true)
trs = append(trs, v)
return dsl.Join(trs...)
}
// PetUpdateOne is the builder for updating a single Pet entity.
type PetUpdateOne struct {
config
id string
}
// Save executes the query and returns the updated entity.
func (puo *PetUpdateOne) Save(ctx context.Context) (*Pet, error) {
switch puo.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return puo.sqlSave(ctx)
case dialect.Neptune:
return puo.gremlinSave(ctx)
default:
return nil, errors.New("entv2: unsupported dialect")
}
}
// SaveX is like Save, but panics if an error occurs.
func (puo *PetUpdateOne) SaveX(ctx context.Context) *Pet {
pe, err := puo.Save(ctx)
if err != nil {
panic(err)
}
return pe
}
// Exec executes the query on the entity.
func (puo *PetUpdateOne) Exec(ctx context.Context) error {
_, err := puo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (puo *PetUpdateOne) ExecX(ctx context.Context) {
if err := puo.Exec(ctx); err != nil {
panic(err)
}
}
func (puo *PetUpdateOne) sqlSave(ctx context.Context) (pe *Pet, err error) {
selector := sql.Select(pet.Columns...).From(sql.Table(pet.Table))
pet.ID(puo.id).SQL(selector)
rows := &sql.Rows{}
query, args := selector.Query()
if err = puo.driver.Query(ctx, query, args, rows); err != nil {
return nil, err
}
defer rows.Close()
var ids []int
for rows.Next() {
var id int
pe = &Pet{config: puo.config}
if err := pe.FromRows(rows); err != nil {
return nil, fmt.Errorf("entv2: failed scanning row into Pet: %v", err)
}
id = pe.id()
ids = append(ids, id)
}
switch n := len(ids); {
case n == 0:
return nil, fmt.Errorf("entv2: Pet not found with id: %v", puo.id)
case n > 1:
return nil, fmt.Errorf("entv2: more than one Pet with the same id: %v", puo.id)
}
tx, err := puo.driver.Tx(ctx)
if err != nil {
return nil, err
}
if err = tx.Commit(); err != nil {
return nil, err
}
return pe, nil
}
func (puo *PetUpdateOne) gremlinSave(ctx context.Context) (*Pet, error) {
res := &gremlin.Response{}
query, bindings := puo.gremlin(puo.id).Query()
if err := puo.driver.Exec(ctx, query, bindings, res); err != nil {
return nil, err
}
if err, ok := isConstantError(res); ok {
return nil, err
}
pe := &Pet{config: puo.config}
if err := pe.FromResponse(res); err != nil {
return nil, err
}
return pe, nil
}
func (puo *PetUpdateOne) gremlin(id string) *dsl.Traversal {
v := g.V(id)
var (
trs []*dsl.Traversal
)
v.ValueMap(true)
trs = append(trs, v)
return dsl.Join(trs...)
}

View File

@@ -22,3 +22,11 @@ func (User) Fields() []ent.Field {
// deleting the address column.
}
}
// Additional types to be added to the schema.
type (
// Pet schema.
Pet struct{ ent.Schema }
// Group schema.
Group struct{ ent.Schema }
)

View File

@@ -13,6 +13,10 @@ import (
// Tx is a transactional client that is created by calling Client.Tx().
type Tx struct {
config
// Group is the client for interacting with the Group builders.
Group *GroupClient
// Pet is the client for interacting with the Pet builders.
Pet *PetClient
// User is the client for interacting with the User builders.
User *UserClient
}
@@ -32,6 +36,8 @@ func (tx *Tx) Client() *Client {
return &Client{
config: tx.config,
Schema: migrate.NewSchema(tx.driver),
Group: NewGroupClient(tx.config),
Pet: NewPetClient(tx.config),
User: NewUserClient(tx.config),
}
}
@@ -43,7 +49,7 @@ func (tx *Tx) Client() *Client {
// of them in order to commit or rollback the transaction.
//
// If a closed transaction is embedded in one of the generated entities, and the entity
// applies a query, for example: User.QueryXXX(), the query will be executed
// applies a query, for example: Group.QueryXXX(), the query will be executed
// through the driver which created this transaction.
//
// Note that this driver is safe for concurrent usage, however, it executes only one query

View File

@@ -93,8 +93,8 @@ func (u *User) Unwrap() *User {
func (u *User) String() string {
buf := bytes.NewBuffer(nil)
buf.WriteString("User(")
buf.WriteString(fmt.Sprintf("id=%v,", u.ID))
buf.WriteString(fmt.Sprintf("age=%v", u.Age))
buf.WriteString(fmt.Sprintf("id=%v", u.ID))
buf.WriteString(fmt.Sprintf(", age=%v", u.Age))
buf.WriteString(fmt.Sprintf(", name=%v", u.Name))
buf.WriteString(fmt.Sprintf(", phone=%v", u.Phone))
buf.WriteString(")")

View File

@@ -2,9 +2,11 @@ package migrate
import (
"context"
"strconv"
"testing"
"fbc/ent/dialect/sql"
"fbc/ent/dialect/sql/schema"
"fbc/ent/entc/integration/migrate/entv1"
"fbc/ent/entc/integration/migrate/entv2"
@@ -27,13 +29,34 @@ func TestMySQL(t *testing.T) {
// run migration and execute queries on v1.
clientv1 := entv1.NewClient(entv1.Driver(drv))
require.NoError(t, clientv1.Schema.Create(ctx))
require.NoError(t, clientv1.Schema.Create(ctx, schema.WithGlobalUniqueID(true)))
SanityV1(t, clientv1)
// run migration and execute queries on v2.
clientv2 := entv2.NewClient(entv2.Driver(drv))
require.NoError(t, clientv2.Schema.Create(ctx))
require.NoError(t, clientv2.Schema.Create(ctx, schema.WithGlobalUniqueID(true)))
SanityV2(t, clientv2)
// since "users" created in the migration of v1, it will occupy the range of 0 ... 1<<32-1,
// even though they are ordered differently in the migration of v2 (groups, pets, users).
idRange(t, clientv2.User.Create().SetAge(1).SetName("foo").SetPhone("100").SaveX(ctx).ID, 0, 1<<32)
idRange(t, clientv2.Group.Create().SaveX(ctx).ID, 1<<32-1, 2<<32)
idRange(t, clientv2.Pet.Create().SaveX(ctx).ID, 2<<32-1, 3<<32)
}
func TestSQLite(t *testing.T) {
drv, err := sql.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
require.NoError(t, err)
defer drv.Close()
ctx := context.Background()
client := entv2.NewClient(entv2.Driver(drv))
require.NoError(t, client.Schema.Create(ctx, schema.WithGlobalUniqueID(true)))
SanityV2(t, client)
idRange(t, client.Group.Create().SaveX(ctx).ID, 0, 1<<32)
idRange(t, client.Pet.Create().SaveX(ctx).ID, 1<<32-1, 2<<32)
idRange(t, client.User.Create().SetAge(1).SetName("x").SetPhone("y").SaveX(ctx).ID, 2<<32, 3<<32-1)
}
func SanityV1(t *testing.T, client *entv1.Client) {
@@ -55,3 +78,9 @@ func SanityV2(t *testing.T, client *entv2.Client) {
_, err := client.User.Create().SetAge(1).SetName("foobarbazqux").SetPhone("100").Save(ctx)
require.NoError(t, err, "name is not limited to 10 chars")
}
func idRange(t *testing.T, s string, l, h int) {
id, err := strconv.Atoi(s)
require.NoError(t, err)
require.Truef(t, id > l && id < h, "id %s should be between %d to %d", s, l, h)
}