ent: add blob tyoe

Reviewed By: idoshveki

Differential Revision: D16600425

fbshipit-source-id: 04c6fe39f9b3b628a1e79eb3063188f582d9e504
This commit is contained in:
Ariel Mashraki
2019-08-01 07:42:14 -07:00
committed by Facebook Github Bot
parent 2d962d5cba
commit c203f043cf
19 changed files with 302 additions and 76 deletions

View File

@@ -184,7 +184,7 @@ func templateBuilderQueryTmpl() (*asset, error) {
return a, nil
}
var _templateBuilderSetterTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x56\xcd\x6e\xdb\x3c\x10\x3c\xcb\x4f\xb1\x9f\xa0\xaf\x90\x8c\x84\x41\xaf\x01\x7c\x29\xdc\xa0\xbe\xa4\x87\xb4\x27\xc3\x28\x14\x73\xe5\xb2\x55\x28\x45\x94\x5c\x04\x2a\xdf\xbd\x58\x92\xfa\x31\x2d\xc7\x0e\x8a\xde\x24\x72\x38\xbb\xdc\x9d\x1d\xa9\x6d\x81\x63\x26\x24\x42\xa8\xb0\xae\xb1\x0a\x41\xeb\x59\xdb\x42\xf4\xd8\x88\x9c\x63\x05\xb7\x0b\x28\x53\xb5\x4d\x73\x88\xd8\xc3\xb6\x28\x91\x7d\x70\x3b\x0e\x58\xe1\x16\xc5\xde\x22\xfb\xe7\xfe\xb8\xd6\x33\x42\x55\xa9\xdc\x21\x44\xdf\xae\x20\xca\x08\x18\xb1\x3b\x81\x39\x57\xb4\x1f\x10\x4b\x49\xab\x79\xf1\x0b\x2b\x88\xcb\x4a\xc8\x3a\x83\xf0\x7f\xf6\x5e\x85\x10\x65\xec\xcb\x4b\x89\x49\x0f\xcd\x1a\xb9\x35\x69\x11\x0c\xc2\x07\xac\x43\x88\xbb\x1c\x33\x76\x9f\x3e\x39\xf0\xcd\x0d\xf4\x78\xad\x41\x61\xad\xa0\xfe\x8e\x76\xd1\xe0\x68\x39\xa3\x44\xd8\x2c\x30\xb0\xf8\xe0\x46\x5a\xc3\x7c\x5c\x0b\xad\x93\x31\x63\x6c\x13\xd7\xda\x31\x52\x9a\x06\xe3\x1d\x82\x76\x16\x04\x1e\x31\xb3\x47\x1e\xea\xaa\xd9\xd6\xa6\x16\x04\x5c\xc0\xbb\x8e\x73\x16\x04\x15\xd6\x4d\x25\xc1\x3b\x39\x0b\x6c\x1d\x44\x06\x45\x45\x1c\x9f\xcb\x5a\x14\xd2\x5d\xbe\xc9\xf3\xf4\x31\x47\x7a\xfe\x94\xaa\x25\x66\x69\x93\xd7\x96\x8e\x78\xa4\xb0\xfb\x77\x47\x35\xbc\x77\x3b\x27\x6a\xd9\x15\xf3\x80\xe0\x4c\x51\x29\x45\xda\xda\x89\x3d\x4a\xd8\xa7\x79\x83\x20\x14\xc8\xa2\x06\x29\x72\x36\x0b\xde\x52\x73\x2f\xf0\x50\xfb\xf9\x05\xc5\x0f\x44\x06\xfd\x81\xff\x16\x14\xde\xae\x4f\xb7\xc5\x85\x98\x77\x47\x12\x82\x52\x11\x4e\xb6\xc4\xf5\x04\x25\x77\x63\xe1\x9e\x3c\xed\xa3\xd5\xfe\x47\xbe\xc3\x41\xfa\x85\xd1\x7e\x98\x72\x4e\xc3\x67\x3b\x1b\x21\xfb\x2a\xc5\x73\x83\x76\x85\x30\x0b\x33\xa2\x0e\xe2\xe8\xcd\x79\xc1\xd5\x61\x3b\xfb\x06\x16\x65\x02\xb1\x12\x72\xd7\xe4\x69\x45\x9c\xa6\x3d\xbf\xdd\x40\x27\x10\xae\x96\xea\x74\xcc\x8e\x77\x9a\xb6\x7b\x41\x27\x92\x70\xb5\xf4\x72\x73\x8a\xe9\x68\xdc\x98\x14\x54\xd0\x41\x32\xd8\x4b\x06\xf9\x0e\xa1\x2e\xdc\x2a\xb5\xb3\xdf\x7a\x7c\x01\xc1\x6d\x92\x24\x9e\x71\xa2\xaa\x0f\xf8\xb6\x11\x1e\xb2\x8a\x8f\x6f\x6f\x82\x61\xae\xec\xb3\x02\xc6\x58\x1f\xc6\x9c\x66\xab\xe5\xeb\x82\x73\x7a\xf3\x95\x85\x47\x03\x3f\xd2\xe2\x65\x07\xe0\x29\xfd\x89\xf1\x53\x5a\xae\xbd\x44\x36\xca\x20\x5b\xa3\x56\x37\xef\x07\xf7\xba\x36\x42\xbd\x28\xcc\x5a\xf0\x0d\x2c\xa0\x63\x6c\x2d\xdd\xb5\xad\x89\xe3\xc9\x8a\x0a\x84\x31\x7d\xa3\x6f\xaa\xd3\xe9\x91\x9a\x08\xa0\xd6\x62\x73\x14\x24\xe8\x23\x39\x11\x9d\x37\xc1\x54\xf2\xd1\x25\x23\x1c\xfc\xf0\xc8\xf5\x56\x4b\x75\x91\xf1\x79\x9a\x3e\x76\xbf\x8e\xc8\x37\xc0\xcb\xd5\xfc\x4f\xbc\x71\x48\x2b\x16\xdc\x42\xcf\x2a\x95\xa4\x2a\xf8\x69\x53\x34\x9a\x9b\x6a\xe9\x68\x82\xe6\x82\xbf\xd5\x22\xcf\x7d\xf4\x47\x35\xeb\xbf\xfc\x22\x03\x7c\xa6\x53\x07\x15\xb1\x44\x0b\x08\xf7\xa1\x7b\x1d\x87\xc8\x5e\x71\x46\xbf\xdd\x13\xff\x0c\x67\x1d\xab\x6d\x7d\x53\x1a\x7b\xd2\xb4\x02\xfe\xfe\x67\x63\xc2\x08\xc7\x1e\x35\xf7\x62\xbe\xf2\x4f\x32\xe5\x10\xd3\x1d\xf4\x9b\xde\xe5\xc3\x56\xcb\x64\xc2\x1e\xc8\x0f\x6e\x9d\x5b\xad\x37\x9e\x14\xaf\x20\x47\xd9\x33\x24\x49\xe7\x4b\xc6\x4f\x42\x31\x7c\x93\xa8\xdf\xc2\xa2\xec\xfe\x02\xc2\x1f\xa3\xef\xcc\xc8\x8b\xec\xbe\xd6\x83\x25\x0d\x15\x33\xaa\x26\xcb\xe9\x40\x1b\x27\x6a\xda\x1e\x16\xd9\x6a\x79\x46\xc6\x7e\x11\x04\x57\x8c\xb1\xc4\x33\xad\xf1\x1f\xc0\xf0\xf4\x27\x00\x00\xff\xff\x6c\x56\x09\x33\x6c\x0b\x00\x00")
var _templateBuilderSetterTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x56\x4d\x6f\xdb\x38\x10\x3d\xcb\xbf\x62\x56\xd0\x2e\x24\x23\xa1\xb1\xd7\x00\xbe\x2c\xbc\x41\x7d\x49\x0f\x6e\x4f\x86\x51\xc8\xe6\xc8\x9d\x56\xa1\x1c\x51\x72\x11\xa8\xfa\xef\x05\x3f\x24\xca\xb4\xec\x38\x28\x7a\x93\xc8\xf9\xe2\xbc\x37\x8f\x6c\x1a\xe0\x98\x91\x40\x08\x25\x56\x15\x96\x21\xb4\xed\xa4\x69\x20\xda\xd6\x94\x73\x2c\xe1\x61\x0e\x87\x54\xee\xd2\x1c\x22\xb6\xda\x15\x07\x64\xff\xd9\x1d\x6b\x58\xe2\x0e\xe9\x68\x2c\xfb\xef\xde\xbd\x6d\x27\xca\xaa\x4c\xc5\x1e\x21\xfa\x72\x07\x51\xa6\x0c\x23\xf6\x48\x98\x73\xa9\xf6\x03\x15\xe5\x70\xea\x9e\xb1\x4f\xaf\x07\x64\xab\xaa\x24\xb1\xef\x8d\xb2\x5a\xec\x74\x41\x25\x89\x0a\xc2\x15\x56\x21\xc4\x5d\x75\x19\x7b\x4a\x9f\x31\xd1\xc6\xb3\x19\xf4\xf6\x6d\x0b\x12\x2b\x09\xd5\x57\x34\x8b\xda\x4e\x2d\x67\xaa\x04\x36\x09\xb4\x59\x7c\x72\x96\xb6\x85\xe9\xb0\x0b\x6d\x9b\x0c\x23\xc6\xa6\xe4\xb6\xb5\x11\x55\xb1\xda\xc6\x73\x82\x66\x12\x04\x5e\x60\x66\x5c\x56\x55\x59\xef\x2a\xdd\x05\x65\x38\x87\x7f\xba\x98\x93\x20\x28\xb1\xaa\x4b\x01\x9e\xe7\x24\xd0\x7d\x98\x4d\x21\x3d\x16\xc4\x61\x8f\x02\xcb\x4a\x35\x48\x50\x9e\xa7\xdb\x1c\xc1\x80\x28\x21\x2b\x4a\x90\x39\xed\x50\xc2\x16\x77\x69\x2d\x51\x9f\x5f\x50\x0e\xc7\x34\xaf\xd1\x19\x00\x49\xb5\x44\x1c\xa6\x33\xdb\x67\xca\x20\x15\x1c\x62\x51\x54\x0e\x09\x65\x9b\x40\x5c\x68\x70\x3e\x1e\x2a\x2a\x84\xed\x7a\x6d\x73\x47\x19\xfb\x90\xca\x05\x66\x69\x9d\x57\x06\x07\x7d\xf6\xae\xb8\xc7\x33\xf4\x9e\xec\xce\x05\x14\x3b\x18\x4f\x02\xbc\x01\xa7\x2a\x5e\x6d\xed\xe9\x88\xc2\x9e\x95\x24\xa8\xa3\x08\xca\xd9\x24\x78\x0f\xda\x5e\x62\x87\xfa\xf4\x06\xd8\x03\xca\xa0\x77\xf8\x6b\xae\x7b\xaf\xd7\xc7\x09\x61\x53\x4c\x3b\x97\x44\x99\xaa\x26\x5c\x24\x83\x61\x03\xa0\xe0\x76\x14\xed\x97\x37\x6f\x68\xe6\xed\x7f\xbe\x47\x37\x6e\x85\x9e\xb7\x30\xe5\x5c\x0d\xbc\xc1\x3c\x42\xf6\x59\xd0\x4b\x8d\x66\x45\xd9\xcc\xb5\x2c\x58\x13\x1b\x5e\xfb\x13\x97\xa7\x70\xf6\x00\x16\x87\x04\x62\x49\x62\x5f\xe7\x69\xa9\x62\x6a\x78\x7e\x5a\x11\x49\x20\x5c\x2e\xe4\xe5\x9c\x5d\xdc\xf1\xb0\xdd\x0f\x5a\x92\x84\xcb\x85\x57\x9b\x65\x4c\x17\xc6\x0e\x68\xa1\x1a\xea\x28\x83\x3d\x65\x90\xef\x11\xaa\xc2\xae\x6a\xa2\x77\x5b\xdb\x57\x20\x6e\x8a\xd4\x73\x30\x28\x54\xf6\x09\xdf\x27\x1e\xae\xaa\xf8\xfc\xf4\x3a\x19\xe6\xd2\x7c\x4b\x60\x8c\xf5\x69\xb4\x37\x5b\x2e\xae\x13\xce\xf2\xcd\x67\x16\x9e\x49\xcd\x80\x8b\xb7\x39\xc0\x73\xfa\x1d\xe3\xe7\xf4\xb0\xf6\x0a\xd9\x48\x6d\xd9\x68\xb6\xda\x79\x3f\x39\xd7\xbd\x26\xea\x4d\x69\xd6\xc4\x37\x30\x87\x2e\x62\x63\xc2\xdd\x9b\x9e\xd8\x38\x4a\xb5\x48\xdf\x14\x9a\xdf\xaa\x4f\x97\x47\x6a\x24\x81\x5c\xd3\xe6\x2c\x49\xd0\x67\xb2\x24\xba\x2e\xbf\x9d\x3c\xba\x43\x46\xe8\x04\xf1\x4c\xf5\x96\x0b\x79\x93\xf0\x79\x9c\x3e\x57\xbf\x2e\x90\x2f\x80\xb7\xb3\xf9\x8f\x68\xa3\x2b\x2b\x56\x77\xc8\x4d\x4c\x55\x54\x25\x7e\x59\x14\x35\xe7\xc6\x20\x1d\x4c\xd0\x94\xf8\x7b\x25\xd2\x3d\x34\xf2\xe2\x07\x96\x10\x6b\x40\x32\x08\xff\x66\xff\xca\xf0\xa4\x67\x09\xb8\xbb\x10\x5f\x94\xd7\x49\x47\x4c\xa0\x39\x84\xc7\xd0\xfe\x0e\x53\x64\x57\x94\xd1\x87\x7b\xe4\xb5\xf2\xa6\x62\x35\x8d\x2f\x4a\x43\x4d\x1a\x67\xc0\xef\x3f\x73\x46\x84\x70\xa8\x51\x53\x2f\xe7\x95\xd7\xd0\x98\x42\x8c\x23\xe8\x83\xde\xd5\xc3\x96\x8b\x64\x44\x1e\x94\x1e\x3c\x58\xb5\x5a\x6f\x3c\x2a\xde\x41\x8e\xa2\x8f\x90\x24\x9d\x2e\x69\x3d\x09\xc9\xdd\x49\x0a\x6f\x32\x56\x66\x7f\x0e\xe1\xb7\xc1\x3d\x33\xd0\x22\xb3\xdf\xb6\x4e\x92\x5c\xc7\x34\xab\x95\xe4\x74\x46\x1b\x4b\x6a\xb5\xed\x16\xd9\x72\xf1\x06\x8d\xfd\x26\x10\x97\x8c\xb1\xc4\x13\xad\xe1\x0b\xc0\x7d\xfd\x0a\x00\x00\xff\xff\x44\xd3\xdd\xc8\xe0\x0b\x00\x00")
func templateBuilderSetterTmplBytes() ([]byte, error) {
return bindataRead(
@@ -199,7 +199,7 @@ func templateBuilderSetterTmpl() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "template/builder/setter.tmpl", size: 2924, mode: os.FileMode(420), modTime: time.Unix(1564665941, 0)}
info := bindataFileInfo{name: "template/builder/setter.tmpl", size: 3040, mode: os.FileMode(420), modTime: time.Unix(1564666719, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}

View File

@@ -117,15 +117,30 @@ func snake(s string) string {
// receiver returns the receiver name of the given type.
//
// []T => t
// User => u
// UserQuery => uq
//
func receiver(s string) (r string) {
words := strings.Split(snake(s), "_")
for _, w := range words {
r += w[:1]
// trim optional operators.
s = strings.Trim(s, "[]*&")
parts := strings.Split(snake(s), "_")
min := len(parts[0])
for _, w := range parts[1:] {
if len(w) < min {
min = len(w)
}
}
return
for i := 1; i < min; i++ {
r := parts[0][:i]
for _, w := range parts[1:] {
r += w[:i]
}
if _, ok := imports[r]; !ok {
return r
}
}
return strings.ToLower(s)
}
// scope wraps the Type object with extended context.

View File

@@ -3,14 +3,11 @@ package gen
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"fbc/ent/dialect/sql/schema"
"fbc/ent/entc/load"
@@ -30,8 +27,6 @@ type (
Header string
// Storage to support in codegen.
Storage []*Storage
// imports are the import packages used for code generation.
imports map[string]string
}
// Graph holds the nodes/entities of the loaded graph schema. Note that, it doesn't
// hold the edges of the graph. Instead, each Type holds the edges for other Types.
@@ -48,7 +43,6 @@ type (
// It fails if one of the schemas is invalid.
func NewGraph(c Config, schemas ...*load.Schema) (g *Graph, err error) {
defer catch(&err)
c.imports = imports()
g = &Graph{c, make([]*Type, 0, len(schemas)), schemas}
for _, schema := range schemas {
g.addNode(schema)
@@ -348,27 +342,6 @@ func (g *Graph) typ(name string) (*Type, bool) {
return nil, false
}
func imports() map[string]string {
var (
specs = make(map[string]string)
b = bytes.NewBuffer([]byte("package main\n"))
)
check(templates.ExecuteTemplate(b, "import", Type{}), "load imports")
f, err := parser.ParseFile(token.NewFileSet(), "", b, parser.ImportsOnly)
check(err, "parse imports")
for _, spec := range f.Imports {
path, err := strconv.Unquote(spec.Path.Value)
check(err, "unquote import path")
specs[filepath.Base(path)] = path
}
for _, s := range drivers {
for _, path := range s.Imports {
specs[filepath.Base(path)] = path
}
}
return specs
}
// expect panic if the condition is false.
func expect(cond bool, msg string, args ...interface{}) {
if !cond {

View File

@@ -1,7 +1,12 @@
package gen
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"path/filepath"
"strconv"
"text/template"
)
@@ -73,12 +78,12 @@ var (
{
Name: "migrate",
Format: "migrate/migrate.go",
Skip: func(g *Graph) bool { return g.migrateSupport() },
Skip: func(g *Graph) bool { return !g.migrateSupport() },
},
{
Name: "schema",
Format: "migrate/schema.go",
Skip: func(g *Graph) bool { return g.migrateSupport() },
Skip: func(g *Graph) bool { return !g.migrateSupport() },
},
{
Name: "predicate",
@@ -90,8 +95,11 @@ var (
},
}
// templates holds the Go templates for the code generation.
// the init function below initializes the templates and its funcs.
// the init function below initializes the templates and its
// funcs to avoid initialization loop.
templates = template.New("templates")
// imports are the import packages used for code generation.
imports = make(map[string]string)
)
func init() {
@@ -99,6 +107,20 @@ func init() {
for _, asset := range AssetNames() {
templates = template.Must(templates.Parse(string(MustAsset(asset))))
}
b := bytes.NewBuffer([]byte("package main\n"))
check(templates.ExecuteTemplate(b, "import", Type{}), "load imports")
f, err := parser.ParseFile(token.NewFileSet(), "", b, parser.ImportsOnly)
check(err, "parse imports")
for _, spec := range f.Imports {
path, err := strconv.Unquote(spec.Path.Value)
check(err, "unquote import path")
imports[filepath.Base(path)] = path
}
for _, s := range drivers {
for _, path := range s.Imports {
imports[filepath.Base(path)] = path
}
}
}
func pkgf(s string) func(t *Type) string {

View File

@@ -3,14 +3,15 @@
{{ $receiver := receiver $builder }}
{{ range $_, $f := $.Fields }}
{{ $p := lower (printf "%.1s" $f.Type) }}
{{ $p := receiver $f.Type.String }}
{{ $func := print "Set" (pascal $f.Name) }}
// {{ $func }} sets the {{ $f.Name }} field.
func ({{ $receiver }} *{{ $builder }}) {{ $func }}({{ $p }} {{ $f.Type }}) *{{ $builder }} {
{{ $receiver }}.{{ $f.StructField }} = &{{ $p }}
return {{ $receiver }}
}
{{ if or $f.Optional $f.Nullable $f.HasDefault }}
{{/* avoid generting nillable setters for slices because the nil value for slice is valid */}}
{{ if and (not $f.Type.Slice) (or $f.Optional $f.Nullable $f.HasDefault) }}
{{ $nillableFunc := print "SetNillable" (pascal $f.Name) }}
// {{ $nillableFunc }} sets the {{ $f.Name }} field if the given value is not nil.
func ({{ $receiver }} *{{ $builder }}) {{ $nillableFunc }}({{ $p }} *{{ $f.Type }}) *{{ $builder }} {

View File

@@ -136,23 +136,7 @@ func (t Type) Package() string { return strings.ToLower(t.Name) }
// Receiver returns the receiver name of this node. It makes sure the
// receiver names doesn't conflict with import names.
func (t Type) Receiver() string {
parts := strings.Split(snake(t.Name), "_")
min := len(parts[0])
for _, w := range parts[1:] {
if len(w) < min {
min = len(w)
}
}
for i := 1; i < min; i++ {
r := parts[0][:i]
for _, w := range parts[1:] {
r += w[:i]
}
if _, ok := t.Config.imports[r]; !ok {
return r
}
}
return strings.ToLower(t.Name)
return receiver(t.Name)
}
// HasAssoc returns true if this type has an assoc edge with the given name.
@@ -317,11 +301,13 @@ func (f Field) Column() *schema.Column {
c.Type = field.TypeInt
c.Increment = true
}
if f.def.Size != nil {
c.Size = *f.def.Size
}
if f.def.Charset != nil {
c.Charset = *f.def.Charset
if f.def != nil {
if f.def.Size != nil {
c.Size = *f.def.Size
}
if f.def.Charset != nil {
c.Charset = *f.def.Charset
}
}
return c
}

View File

@@ -68,9 +68,10 @@ func TestType_Receiver(t *testing.T) {
{"PHBUser", "pu"},
{"PHBOrg", "po"},
{"DomainSpecificLang", "dospla"},
{"[]byte", "b"},
}
for _, tt := range tests {
typ := &Type{Name: tt.name, Config: Config{Package: "entc/gen", imports: imports()}}
typ := &Type{Name: tt.name, Config: Config{Package: "entc/gen"}}
require.Equal(t, tt.receiver, typ.Receiver())
}
}

View File

@@ -80,6 +80,7 @@ func ExampleUser() {
SetAge(1).
SetName("string").
SetPhone("string").
SetBuffer(1).
SaveX(ctx)
log.Println("user created:", u)

View File

@@ -37,6 +37,7 @@ var (
{Name: "age", Type: field.TypeInt},
{Name: "name", Type: field.TypeString, Size: 2147483647},
{Name: "phone", Type: field.TypeString},
{Name: "buffer", Type: field.TypeBytes},
}
// UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{

View File

@@ -17,8 +17,10 @@ func (User) Fields() []ent.Field {
field.Int("age"),
// extending name field to longtext.
field.Text("name"),
// adding new column.
// adding new columns.
field.String("phone"),
field.Bytes("buffer").
Default([]byte("{}")),
// deleting the address column.
}
}

View File

@@ -21,15 +21,18 @@ type User struct {
Name string `json:"name,omitempty"`
// Phone holds the value of the "phone" field.
Phone string `json:"phone,omitempty"`
// Buffer holds the value of the "buffer" field.
Buffer []byte `json:"buffer,omitempty"`
}
// FromRows scans the sql response data into User.
func (u *User) FromRows(rows *sql.Rows) error {
var vu struct {
ID int
Age int
Name string
Phone string
ID int
Age int
Name string
Phone string
Buffer []byte
}
// the order here should be the same as in the `user.Columns`.
if err := rows.Scan(
@@ -37,6 +40,7 @@ func (u *User) FromRows(rows *sql.Rows) error {
&vu.Age,
&vu.Name,
&vu.Phone,
&vu.Buffer,
); err != nil {
return err
}
@@ -44,6 +48,7 @@ func (u *User) FromRows(rows *sql.Rows) error {
u.Age = vu.Age
u.Name = vu.Name
u.Phone = vu.Phone
u.Buffer = vu.Buffer
return nil
}
@@ -73,6 +78,7 @@ func (u *User) String() string {
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(fmt.Sprintf(", buffer=%v", u.Buffer))
buf.WriteString(")")
return buf.String()
}

View File

@@ -2,6 +2,10 @@
package user
import (
"fbc/ent/entc/integration/migrate/entv2/schema"
)
const (
// Label holds the string label denoting the user type in the database.
Label = "user"
@@ -13,6 +17,8 @@ const (
FieldName = "name"
// FieldPhone holds the string denoting the phone vertex property in the database.
FieldPhone = "phone"
// FieldBuffer holds the string denoting the buffer vertex property in the database.
FieldBuffer = "buffer"
// Table holds the table name of the user in the database.
Table = "users"
@@ -24,4 +30,11 @@ var Columns = []string{
FieldAge,
FieldName,
FieldPhone,
FieldBuffer,
}
var (
fields = schema.User{}.Fields()
// DefaultBuffer holds the default value for the buffer field.
DefaultBuffer = fields[3].Value().([]byte)
)

View File

@@ -145,6 +145,15 @@ func Phone(v string) predicate.User {
)
}
// Buffer applies equality check predicate on the "buffer" field. It's identical to BufferEQ.
func Buffer(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldBuffer), v))
},
)
}
// AgeEQ applies the EQ predicate on the "age" field.
func AgeEQ(v int) predicate.User {
return predicate.User(
@@ -475,6 +484,98 @@ func PhoneHasSuffix(v string) predicate.User {
)
}
// BufferEQ applies the EQ predicate on the "buffer" field.
func BufferEQ(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldBuffer), v))
},
)
}
// BufferNEQ applies the NEQ predicate on the "buffer" field.
func BufferNEQ(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldBuffer), v))
},
)
}
// BufferGT applies the GT predicate on the "buffer" field.
func BufferGT(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldBuffer), v))
},
)
}
// BufferGTE applies the GTE predicate on the "buffer" field.
func BufferGTE(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldBuffer), v))
},
)
}
// BufferLT applies the LT predicate on the "buffer" field.
func BufferLT(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldBuffer), v))
},
)
}
// BufferLTE applies the LTE predicate on the "buffer" field.
func BufferLTE(v []byte) predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldBuffer), v))
},
)
}
// BufferIn applies the In predicate on the "buffer" field.
func BufferIn(vs ...[]byte) predicate.User {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.User(
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(vs) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldBuffer), v...))
},
)
}
// BufferNotIn applies the NotIn predicate on the "buffer" field.
func BufferNotIn(vs ...[]byte) predicate.User {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.User(
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(vs) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldBuffer), v...))
},
)
}
// Or groups list of predicates with the or operator between them.
func Or(predicates ...predicate.User) predicate.User {
return predicate.User(

View File

@@ -16,9 +16,10 @@ import (
// UserCreate is the builder for creating a User entity.
type UserCreate struct {
config
age *int
name *string
phone *string
age *int
name *string
phone *string
buffer *[]byte
}
// SetAge sets the age field.
@@ -39,6 +40,12 @@ func (uc *UserCreate) SetPhone(s string) *UserCreate {
return uc
}
// SetBuffer sets the buffer field.
func (uc *UserCreate) SetBuffer(b []byte) *UserCreate {
uc.buffer = &b
return uc
}
// Save creates the User in the database.
func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
if uc.age == nil {
@@ -50,6 +57,10 @@ func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
if uc.phone == nil {
return nil, errors.New("entv2: missing required field \"phone\"")
}
if uc.buffer == nil {
v := user.DefaultBuffer
uc.buffer = &v
}
switch uc.driver.Dialect() {
case dialect.MySQL, dialect.SQLite:
return uc.sqlSave(ctx)
@@ -89,6 +100,10 @@ func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) {
builder.Set(user.FieldPhone, *uc.phone)
u.Phone = *uc.phone
}
if uc.buffer != nil {
builder.Set(user.FieldBuffer, *uc.buffer)
u.Buffer = *uc.buffer
}
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
return nil, rollback(tx, err)

View File

@@ -20,6 +20,7 @@ type UserUpdate struct {
age *int
name *string
phone *string
buffer *[]byte
predicates []predicate.User
}
@@ -47,6 +48,12 @@ func (uu *UserUpdate) SetPhone(s string) *UserUpdate {
return uu
}
// SetBuffer sets the buffer field.
func (uu *UserUpdate) SetBuffer(b []byte) *UserUpdate {
uu.buffer = &b
return uu
}
// Save executes the query and returns the number of rows/vertices matched by this operation.
func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
switch uu.driver.Dialect() {
@@ -123,6 +130,10 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
update = true
builder.Set(user.FieldPhone, *uu.phone)
}
if uu.buffer != nil {
update = true
builder.Set(user.FieldBuffer, *uu.buffer)
}
if update {
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
@@ -138,10 +149,11 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
// UserUpdateOne is the builder for updating a single User entity.
type UserUpdateOne struct {
config
id string
age *int
name *string
phone *string
id string
age *int
name *string
phone *string
buffer *[]byte
}
// SetAge sets the age field.
@@ -162,6 +174,12 @@ func (uuo *UserUpdateOne) SetPhone(s string) *UserUpdateOne {
return uuo
}
// SetBuffer sets the buffer field.
func (uuo *UserUpdateOne) SetBuffer(b []byte) *UserUpdateOne {
uuo.buffer = &b
return uuo
}
// Save executes the query and returns the updated entity.
func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) {
switch uuo.driver.Dialect() {
@@ -244,6 +262,11 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) {
builder.Set(user.FieldPhone, *uuo.phone)
u.Phone = *uuo.phone
}
if uuo.buffer != nil {
update = true
builder.Set(user.FieldBuffer, *uuo.buffer)
u.Buffer = *uuo.buffer
}
if update {
query, args := builder.Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {

View File

@@ -74,6 +74,9 @@ func SanityV2(t *testing.T, client *entv2.Client) {
u := client.User.Create().SetAge(1).SetName("bar").SetPhone("100").SaveX(ctx)
require.Equal(t, 1, u.Age)
require.Equal(t, "bar", u.Name)
require.Equal(t, []byte("{}"), u.Buffer)
u = u.Update().SetBuffer([]byte("[]")).SaveX(ctx)
require.Equal(t, []byte("[]"), u.Buffer)
_, err := client.User.Create().SetAge(1).SetName("foobarbazqux").SetPhone("100").Save(ctx)
require.NoError(t, err, "name is not limited to 10 chars")