mirror of
https://github.com/ent/ent.git
synced 2026-03-05 19:35:23 +03:00
schema/field: add support or external ValueScanner (#3391)
This commit is contained in:
@@ -7,6 +7,7 @@ package field
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -84,7 +85,8 @@ func JSON(name string, typ any) *jsonBuilder {
|
||||
}
|
||||
b.desc.Info.Ident = t.String()
|
||||
b.desc.Info.PkgPath = t.PkgPath()
|
||||
b.desc.goType(typ, t)
|
||||
b.desc.goType(typ)
|
||||
b.desc.checkGoType(t)
|
||||
switch t.Kind() {
|
||||
case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Map:
|
||||
b.desc.Info.Nillable = true
|
||||
@@ -156,7 +158,7 @@ func UUID(name string, typ driver.Valuer) *uuidBuilder {
|
||||
PkgPath: indirect(rt).PkgPath(),
|
||||
},
|
||||
}}
|
||||
b.desc.goType(typ, valueScannerType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -176,7 +178,7 @@ func Other(name string, typ driver.Valuer) *otherBuilder {
|
||||
Name: name,
|
||||
Info: &TypeInfo{Type: TypeOther},
|
||||
}}
|
||||
ob.desc.goType(typ, valueScannerType)
|
||||
ob.desc.goType(typ)
|
||||
return ob
|
||||
}
|
||||
|
||||
@@ -324,7 +326,16 @@ func (b *stringBuilder) SchemaType(types map[string]string) *stringBuilder {
|
||||
// field.String("dir").
|
||||
// GoType(http.Dir("dir"))
|
||||
func (b *stringBuilder) GoType(typ any) *stringBuilder {
|
||||
b.desc.goType(typ, stringType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces, such as slices and maps
|
||||
// or types exist in external packages (e.g., url.URL).
|
||||
func (b *stringBuilder) ValueScanner(vs any) *stringBuilder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -345,6 +356,7 @@ func (b *stringBuilder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil {
|
||||
b.desc.checkDefaultFunc(stringType)
|
||||
}
|
||||
b.desc.checkGoType(stringType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -427,7 +439,7 @@ func (b *timeBuilder) StorageKey(key string) *timeBuilder {
|
||||
// field.Time("deleted_at").
|
||||
// GoType(&sql.NullTime{})
|
||||
func (b *timeBuilder) GoType(typ any) *timeBuilder {
|
||||
b.desc.goType(typ, timeType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -448,6 +460,7 @@ func (b *timeBuilder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil {
|
||||
b.desc.checkDefaultFunc(timeType)
|
||||
}
|
||||
b.desc.checkGoType(timeType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -522,7 +535,7 @@ func (b *boolBuilder) StorageKey(key string) *boolBuilder {
|
||||
// field.Bool("deleted").
|
||||
// GoType(&sql.NullBool{})
|
||||
func (b *boolBuilder) GoType(typ any) *boolBuilder {
|
||||
b.desc.goType(typ, boolType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -540,6 +553,7 @@ func (b *boolBuilder) Annotations(annotations ...schema.Annotation) *boolBuilder
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *boolBuilder) Descriptor() *Descriptor {
|
||||
b.desc.checkGoType(boolType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -673,7 +687,7 @@ func (b *bytesBuilder) StorageKey(key string) *bytesBuilder {
|
||||
// field.Bytes("ip").
|
||||
// GoType(net.IP("127.0.0.1"))
|
||||
func (b *bytesBuilder) GoType(typ any) *bytesBuilder {
|
||||
b.desc.goType(typ, bytesType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -702,6 +716,7 @@ func (b *bytesBuilder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil {
|
||||
b.desc.checkDefaultFunc(bytesType)
|
||||
}
|
||||
b.desc.checkGoType(bytesType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -916,18 +931,20 @@ type EnumValues interface {
|
||||
// GoType(role.Enum("role"))
|
||||
func (b *enumBuilder) GoType(ev EnumValues) *enumBuilder {
|
||||
b.Values(ev.Values()...)
|
||||
b.desc.goType(ev, stringType)
|
||||
// If an error already exists, let that be returned instead.
|
||||
// Otherwise, check that the underlying type is either a string
|
||||
// or implements Stringer.
|
||||
if b.desc.Err == nil && b.desc.Info.RType.rtype.Kind() != reflect.String && !b.desc.Info.Stringer() {
|
||||
b.desc.Err = errors.New("enum values which implement ValueScanner must also implement Stringer")
|
||||
}
|
||||
b.desc.goType(ev)
|
||||
return b
|
||||
}
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *enumBuilder) Descriptor() *Descriptor {
|
||||
if b.desc.Info.RType != nil {
|
||||
// If an error already exists, let that be returned instead.
|
||||
// Otherwise, check that the underlying type is either a string or implements Stringer.
|
||||
if b.desc.Err == nil && b.desc.Info.RType.rtype.Kind() != reflect.String && !b.desc.Info.Stringer() {
|
||||
b.desc.Err = errors.New("enum values which implement ValueScanner must also implement Stringer")
|
||||
}
|
||||
b.desc.checkGoType(stringType)
|
||||
}
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1022,6 +1039,7 @@ func (b *uuidBuilder) Annotations(annotations ...schema.Annotation) *uuidBuilder
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *uuidBuilder) Descriptor() *Descriptor {
|
||||
b.desc.checkGoType(valueScannerType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1141,6 +1159,7 @@ func (b *otherBuilder) Annotations(annotations ...schema.Annotation) *otherBuild
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *otherBuilder) Descriptor() *Descriptor {
|
||||
b.desc.checkGoType(valueScannerType)
|
||||
if len(b.desc.SchemaType) == 0 {
|
||||
b.desc.Err = fmt.Errorf("expect SchemaType to be set for other field")
|
||||
}
|
||||
@@ -1153,6 +1172,7 @@ type Descriptor struct {
|
||||
Size int // varchar size.
|
||||
Name string // field name.
|
||||
Info *TypeInfo // field type info.
|
||||
ValueScanner any // custom field codec.
|
||||
Unique bool // unique index of field.
|
||||
Nillable bool // nillable struct field.
|
||||
Optional bool // nullable field in database.
|
||||
@@ -1169,7 +1189,7 @@ type Descriptor struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (d *Descriptor) goType(typ any, expectType reflect.Type) {
|
||||
func (d *Descriptor) goType(typ any) {
|
||||
t := reflect.TypeOf(typ)
|
||||
tv := indirect(t)
|
||||
info := &TypeInfo{
|
||||
@@ -1191,15 +1211,40 @@ func (d *Descriptor) goType(typ any, expectType reflect.Type) {
|
||||
case reflect.Slice, reflect.Ptr, reflect.Map:
|
||||
info.Nillable = true
|
||||
}
|
||||
switch pt := reflect.PtrTo(t); {
|
||||
case pt.Implements(valueScannerType), t.Implements(valueScannerType),
|
||||
t.Kind() == expectType.Kind() && t.ConvertibleTo(expectType):
|
||||
default:
|
||||
d.Err = fmt.Errorf("GoType must be a %q type or ValueScanner", expectType)
|
||||
}
|
||||
d.Info = info
|
||||
}
|
||||
|
||||
func (d *Descriptor) checkGoType(expectType reflect.Type) {
|
||||
t := expectType
|
||||
if d.Info.RType != nil && d.Info.RType.rtype != nil {
|
||||
t = d.Info.RType.rtype
|
||||
}
|
||||
switch pt := reflect.PtrTo(t); {
|
||||
// An external ValueScanner.
|
||||
case d.ValueScanner != nil:
|
||||
vs := reflect.Indirect(reflect.ValueOf(d.ValueScanner)).Type()
|
||||
m1, ok1 := vs.MethodByName("Value")
|
||||
m2, ok2 := vs.MethodByName("ScanValue")
|
||||
m3, ok3 := vs.MethodByName("FromValue")
|
||||
switch {
|
||||
case !ok1, m1.Type.NumIn() != 2, m1.Type.In(1) != t,
|
||||
m1.Type.NumOut() != 2, m1.Type.Out(0) != valueType, m1.Type.Out(1) != errorType:
|
||||
d.Err = fmt.Errorf("ValueScanner must implement the Value method: func Value(%s) (driver.Valuer, error)", t)
|
||||
case !ok2, m2.Type.NumIn() != 1, m2.Type.NumOut() != 1, m2.Type.Out(0) != valueScannerType:
|
||||
d.Err = errors.New("ValueScanner must implement the ScanValue method: func ScanValue() field.ValueScanner")
|
||||
case !ok3, m3.Type.NumIn() != 2, m3.Type.In(1) != valueType, m3.Type.NumOut() != 2, m3.Type.Out(0) != t, m3.Type.Out(1) != errorType:
|
||||
d.Err = fmt.Errorf("ValueScanner must implement the FromValue method: func FromValue(driver.Valuer) (%s, error)", t)
|
||||
}
|
||||
// No GoType was provided.
|
||||
case d.Info.RType == nil:
|
||||
// A GoType without an external ValueScanner.
|
||||
case pt.Implements(valueScannerType), t.Implements(valueScannerType), t.Kind() == expectType.Kind() && t.ConvertibleTo(expectType):
|
||||
// There is a GoType, but it's not a ValueScanner.
|
||||
default:
|
||||
d.Err = fmt.Errorf("GoType must be a %q type, ValueScanner or provide an external ValueScanner", expectType)
|
||||
}
|
||||
}
|
||||
|
||||
// pkgName returns the package name from a Go
|
||||
// identifier with a package qualifier.
|
||||
func pkgName(ident string) string {
|
||||
@@ -1261,17 +1306,130 @@ var (
|
||||
bytesType = reflect.TypeOf([]byte(nil))
|
||||
timeType = reflect.TypeOf(time.Time{})
|
||||
stringType = reflect.TypeOf("")
|
||||
valueType = reflect.TypeOf((*driver.Value)(nil)).Elem()
|
||||
valuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
valueScannerType = reflect.TypeOf((*ValueScanner)(nil)).Elem()
|
||||
validatorType = reflect.TypeOf((*Validator)(nil)).Elem()
|
||||
)
|
||||
|
||||
// ValueScanner is the interface that groups the Value and the Scan methods.
|
||||
// ValueScanner is the interface that groups the Value
|
||||
// and the Scan methods implemented by custom Go types.
|
||||
type ValueScanner interface {
|
||||
driver.Valuer
|
||||
sql.Scanner
|
||||
}
|
||||
|
||||
// TypeValueScanner is the interface that groups all methods for
|
||||
// attaching an external ValueScanner to a custom GoType.
|
||||
type TypeValueScanner[T any] interface {
|
||||
// Value returns the driver.Valuer for the GoType.
|
||||
Value(T) (driver.Value, error)
|
||||
// ScanValue returns a new ValueScanner that functions as an
|
||||
// intermediate result between database value and GoType value.
|
||||
// For example, sql.NullString or sql.NullInt.
|
||||
ScanValue() ValueScanner
|
||||
// FromValue returns the field instance from the ScanValue
|
||||
// above after the database value was scanned.
|
||||
FromValue(driver.Value) (T, error)
|
||||
}
|
||||
|
||||
// TextValueScanner returns a new TypeValueScanner that calls MarshalText
|
||||
// for storing values in the database, and calls UnmarshalText for scanning
|
||||
// database values into struct fields.
|
||||
type TextValueScanner[T interface {
|
||||
encoding.TextMarshaler
|
||||
encoding.TextUnmarshaler
|
||||
}] struct{}
|
||||
|
||||
// Value implements the TypeValueScanner.Value method.
|
||||
func (TextValueScanner[T]) Value(v T) (driver.Value, error) {
|
||||
return v.MarshalText()
|
||||
}
|
||||
|
||||
// ScanValue implements the TypeValueScanner.ScanValue method.
|
||||
func (TextValueScanner[T]) ScanValue() ValueScanner {
|
||||
return &sql.NullString{}
|
||||
}
|
||||
|
||||
// FromValue implements the TypeValueScanner.FromValue method.
|
||||
func (TextValueScanner[T]) FromValue(v driver.Value) (tv T, err error) {
|
||||
s, ok := v.(*sql.NullString)
|
||||
if !ok {
|
||||
return tv, fmt.Errorf("unexpected input for FromValue: %T", v)
|
||||
}
|
||||
tv = newT(tv).(T)
|
||||
if s.Valid {
|
||||
err = tv.UnmarshalText([]byte(s.String))
|
||||
}
|
||||
return tv, err
|
||||
}
|
||||
|
||||
// BinaryValueScanner returns a new TypeValueScanner that calls MarshalBinary
|
||||
// for storing values in the database, and calls UnmarshalBinary for scanning
|
||||
// database values into struct fields.
|
||||
type BinaryValueScanner[T interface {
|
||||
encoding.BinaryMarshaler
|
||||
encoding.BinaryUnmarshaler
|
||||
}] struct{}
|
||||
|
||||
// Value implements the TypeValueScanner.Value method.
|
||||
func (BinaryValueScanner[T]) Value(v T) (driver.Value, error) {
|
||||
return v.MarshalBinary()
|
||||
}
|
||||
|
||||
// ScanValue implements the TypeValueScanner.ScanValue method.
|
||||
func (BinaryValueScanner[T]) ScanValue() ValueScanner {
|
||||
return &sql.NullString{}
|
||||
}
|
||||
|
||||
// FromValue implements the TypeValueScanner.FromValue method.
|
||||
func (BinaryValueScanner[T]) FromValue(v driver.Value) (tv T, err error) {
|
||||
s, ok := v.(*sql.NullString)
|
||||
if !ok {
|
||||
return tv, fmt.Errorf("unexpected input for FromValue: %T", v)
|
||||
}
|
||||
tv = newT(tv).(T)
|
||||
if s.Valid {
|
||||
err = tv.UnmarshalBinary([]byte(s.String))
|
||||
}
|
||||
return tv, err
|
||||
}
|
||||
|
||||
// ValueScannerFunc is a wrapper for a function that implements the ValueScanner.
|
||||
type ValueScannerFunc[T any, S ValueScanner] struct {
|
||||
V func(T) (driver.Value, error)
|
||||
S func(S) (T, error)
|
||||
}
|
||||
|
||||
// Value implements the TypeValueScanner.Value method.
|
||||
func (f ValueScannerFunc[T, S]) Value(t T) (driver.Value, error) {
|
||||
return f.V(t)
|
||||
}
|
||||
|
||||
// ScanValue implements the TypeValueScanner.ScanValue method.
|
||||
func (f ValueScannerFunc[T, S]) ScanValue() ValueScanner {
|
||||
var s S
|
||||
return newT(s).(S)
|
||||
}
|
||||
|
||||
// FromValue implements the TypeValueScanner.FromValue method.
|
||||
func (f ValueScannerFunc[T, S]) FromValue(v driver.Value) (tv T, err error) {
|
||||
s, ok := v.(S)
|
||||
if !ok {
|
||||
return tv, fmt.Errorf("unexpected input for FromValue: %T", v)
|
||||
}
|
||||
return f.S(s)
|
||||
}
|
||||
|
||||
// newT ensures the type is initialized.
|
||||
func newT(t any) any {
|
||||
if rt := reflect.TypeOf(t); rt.Kind() == reflect.Ptr {
|
||||
return reflect.New(rt.Elem()).Interface()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Validator interface wraps the Validate method. Custom GoTypes with
|
||||
// this method will be validated when the entity is created or updated.
|
||||
type Validator interface {
|
||||
|
||||
@@ -7,6 +7,7 @@ package field_test
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -25,6 +26,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestInt(t *testing.T) {
|
||||
@@ -89,7 +91,7 @@ func TestInt(t *testing.T) {
|
||||
assert.True(t, fd.Info.ValueScanner())
|
||||
|
||||
fd = field.Int("count").GoType(false).Descriptor()
|
||||
assert.EqualError(t, fd.Err, `GoType must be a "int" type or ValueScanner`)
|
||||
assert.EqualError(t, fd.Err, `GoType must be a "int" type, ValueScanner or provide an external ValueScanner`)
|
||||
fd = field.Int("count").GoType(struct{}{}).Descriptor()
|
||||
assert.Error(t, fd.Err)
|
||||
fd = field.Int("count").GoType(new(Count)).Descriptor()
|
||||
@@ -312,6 +314,38 @@ func TestString_DefaultFunc(t *testing.T) {
|
||||
assert.EqualError(t, fd.Err, `field.String("str").DefaultFunc expects func but got string`)
|
||||
}
|
||||
|
||||
func TestString_ValueScanner(t *testing.T) {
|
||||
fd := field.String("dir").
|
||||
ValueScanner(field.ValueScannerFunc[string, *sql.NullString]{
|
||||
V: func(s string) (driver.Value, error) {
|
||||
return base64.StdEncoding.EncodeToString([]byte(s)), nil
|
||||
},
|
||||
S: func(ns *sql.NullString) (string, error) {
|
||||
if !ns.Valid {
|
||||
return "", nil
|
||||
}
|
||||
b, err := base64.StdEncoding.DecodeString(ns.String)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
},
|
||||
}).Descriptor()
|
||||
require.NoError(t, fd.Err)
|
||||
require.NotNil(t, fd.ValueScanner)
|
||||
_, ok := fd.ValueScanner.(field.TypeValueScanner[string])
|
||||
require.True(t, ok)
|
||||
|
||||
fd = field.String("url").
|
||||
GoType(&url.URL{}).
|
||||
ValueScanner(field.BinaryValueScanner[*url.URL]{}).
|
||||
Descriptor()
|
||||
require.NoError(t, fd.Err)
|
||||
require.NotNil(t, fd.ValueScanner)
|
||||
_, ok = fd.ValueScanner.(field.TypeValueScanner[*url.URL])
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
type VString string
|
||||
|
||||
func (s *VString) Scan(any) error {
|
||||
|
||||
@@ -205,7 +205,15 @@ func (b *{{ $builder }}) SchemaType(types map[string]string) *{{ $builder }} {
|
||||
// }
|
||||
//
|
||||
func (b *{{ $builder }}) GoType(typ any) *{{ $builder }} {
|
||||
b.desc.goType(typ, {{ $t }}Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *{{ $builder }}) ValueScanner(vs any) *{{ $builder }} {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -225,6 +233,7 @@ func (b *{{ $builder }}) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc({{ $t }}Type)
|
||||
}
|
||||
b.desc.checkGoType({{ $t }}Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -377,7 +386,15 @@ func (b *{{ $builder }}) SchemaType(types map[string]string) *{{ $builder }} {
|
||||
// }
|
||||
//
|
||||
func (b *{{ $builder }}) GoType(typ any) *{{ $builder }} {
|
||||
b.desc.goType(typ, {{ $t }}Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *{{ $builder }}) ValueScanner(vs any) *{{ $builder }} {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -394,6 +411,7 @@ func (b *{{ $builder }}) Annotations(annotations ...schema.Annotation) *{{ $buil
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *{{ $builder }}) Descriptor() *Descriptor {
|
||||
b.desc.checkGoType({{ $t }}Type)
|
||||
return b.desc
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
@@ -267,7 +267,15 @@ func (b *intBuilder) SchemaType(types map[string]string) *intBuilder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *intBuilder) GoType(typ any) *intBuilder {
|
||||
b.desc.goType(typ, intType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *intBuilder) ValueScanner(vs any) *intBuilder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -286,6 +294,7 @@ func (b *intBuilder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(intType)
|
||||
}
|
||||
b.desc.checkGoType(intType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -435,7 +444,15 @@ func (b *uintBuilder) SchemaType(types map[string]string) *uintBuilder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *uintBuilder) GoType(typ any) *uintBuilder {
|
||||
b.desc.goType(typ, uintType)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *uintBuilder) ValueScanner(vs any) *uintBuilder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -454,6 +471,7 @@ func (b *uintBuilder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(uintType)
|
||||
}
|
||||
b.desc.checkGoType(uintType)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -613,7 +631,15 @@ func (b *int8Builder) SchemaType(types map[string]string) *int8Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *int8Builder) GoType(typ any) *int8Builder {
|
||||
b.desc.goType(typ, int8Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *int8Builder) ValueScanner(vs any) *int8Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -632,6 +658,7 @@ func (b *int8Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(int8Type)
|
||||
}
|
||||
b.desc.checkGoType(int8Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -791,7 +818,15 @@ func (b *int16Builder) SchemaType(types map[string]string) *int16Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *int16Builder) GoType(typ any) *int16Builder {
|
||||
b.desc.goType(typ, int16Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *int16Builder) ValueScanner(vs any) *int16Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -810,6 +845,7 @@ func (b *int16Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(int16Type)
|
||||
}
|
||||
b.desc.checkGoType(int16Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -969,7 +1005,15 @@ func (b *int32Builder) SchemaType(types map[string]string) *int32Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *int32Builder) GoType(typ any) *int32Builder {
|
||||
b.desc.goType(typ, int32Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *int32Builder) ValueScanner(vs any) *int32Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -988,6 +1032,7 @@ func (b *int32Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(int32Type)
|
||||
}
|
||||
b.desc.checkGoType(int32Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1147,7 +1192,15 @@ func (b *int64Builder) SchemaType(types map[string]string) *int64Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *int64Builder) GoType(typ any) *int64Builder {
|
||||
b.desc.goType(typ, int64Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *int64Builder) ValueScanner(vs any) *int64Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -1166,6 +1219,7 @@ func (b *int64Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(int64Type)
|
||||
}
|
||||
b.desc.checkGoType(int64Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1315,7 +1369,15 @@ func (b *uint8Builder) SchemaType(types map[string]string) *uint8Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *uint8Builder) GoType(typ any) *uint8Builder {
|
||||
b.desc.goType(typ, uint8Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *uint8Builder) ValueScanner(vs any) *uint8Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -1334,6 +1396,7 @@ func (b *uint8Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(uint8Type)
|
||||
}
|
||||
b.desc.checkGoType(uint8Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1483,7 +1546,15 @@ func (b *uint16Builder) SchemaType(types map[string]string) *uint16Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *uint16Builder) GoType(typ any) *uint16Builder {
|
||||
b.desc.goType(typ, uint16Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *uint16Builder) ValueScanner(vs any) *uint16Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -1502,6 +1573,7 @@ func (b *uint16Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(uint16Type)
|
||||
}
|
||||
b.desc.checkGoType(uint16Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1651,7 +1723,15 @@ func (b *uint32Builder) SchemaType(types map[string]string) *uint32Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *uint32Builder) GoType(typ any) *uint32Builder {
|
||||
b.desc.goType(typ, uint32Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *uint32Builder) ValueScanner(vs any) *uint32Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -1670,6 +1750,7 @@ func (b *uint32Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(uint32Type)
|
||||
}
|
||||
b.desc.checkGoType(uint32Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1819,7 +1900,15 @@ func (b *uint64Builder) SchemaType(types map[string]string) *uint64Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *uint64Builder) GoType(typ any) *uint64Builder {
|
||||
b.desc.goType(typ, uint64Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *uint64Builder) ValueScanner(vs any) *uint64Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -1838,6 +1927,7 @@ func (b *uint64Builder) Descriptor() *Descriptor {
|
||||
if b.desc.Default != nil || b.desc.UpdateDefault != nil {
|
||||
b.desc.checkDefaultFunc(uint64Type)
|
||||
}
|
||||
b.desc.checkGoType(uint64Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -1988,7 +2078,15 @@ func (b *float64Builder) SchemaType(types map[string]string) *float64Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *float64Builder) GoType(typ any) *float64Builder {
|
||||
b.desc.goType(typ, float64Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *float64Builder) ValueScanner(vs any) *float64Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -2004,6 +2102,7 @@ func (b *float64Builder) Annotations(annotations ...schema.Annotation) *float64B
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *float64Builder) Descriptor() *Descriptor {
|
||||
b.desc.checkGoType(float64Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
@@ -2141,7 +2240,15 @@ func (b *float32Builder) SchemaType(types map[string]string) *float32Builder {
|
||||
// return add(t1, t2)
|
||||
// }
|
||||
func (b *float32Builder) GoType(typ any) *float32Builder {
|
||||
b.desc.goType(typ, float32Type)
|
||||
b.desc.goType(typ)
|
||||
return b
|
||||
}
|
||||
|
||||
// ValueScanner provides an external value scanner for the given GoType.
|
||||
// Using this option allow users to use field types that do not implement
|
||||
// the sql.Scanner and driver.Valuer interfaces.
|
||||
func (b *float32Builder) ValueScanner(vs any) *float32Builder {
|
||||
b.desc.ValueScanner = vs
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -2157,6 +2264,7 @@ func (b *float32Builder) Annotations(annotations ...schema.Annotation) *float32B
|
||||
|
||||
// Descriptor implements the ent.Field interface by returning its descriptor.
|
||||
func (b *float32Builder) Descriptor() *Descriptor {
|
||||
b.desc.checkGoType(float32Type)
|
||||
return b.desc
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user