summaryrefslogtreecommitdiff
path: root/vendor/github.com/uptrace/bun/schema/append_value.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/uptrace/bun/schema/append_value.go')
-rw-r--r--vendor/github.com/uptrace/bun/schema/append_value.go112
1 files changed, 75 insertions, 37 deletions
diff --git a/vendor/github.com/uptrace/bun/schema/append_value.go b/vendor/github.com/uptrace/bun/schema/append_value.go
index 8fe8a13b2..c93f5b291 100644
--- a/vendor/github.com/uptrace/bun/schema/append_value.go
+++ b/vendor/github.com/uptrace/bun/schema/append_value.go
@@ -7,12 +7,14 @@ import (
"reflect"
"strconv"
"strings"
+ "sync"
"time"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/sqltype"
"github.com/uptrace/bun/extra/bunjson"
"github.com/uptrace/bun/internal"
+ "github.com/vmihailenco/msgpack/v5"
)
type (
@@ -30,8 +32,8 @@ var appenders = []AppenderFunc{
reflect.Uint: AppendUintValue,
reflect.Uint8: AppendUintValue,
reflect.Uint16: AppendUintValue,
- reflect.Uint32: AppendUintValue,
- reflect.Uint64: AppendUintValue,
+ reflect.Uint32: appendUint32Value,
+ reflect.Uint64: appendUint64Value,
reflect.Uintptr: nil,
reflect.Float32: AppendFloat32Value,
reflect.Float64: AppendFloat64Value,
@@ -49,6 +51,8 @@ var appenders = []AppenderFunc{
reflect.UnsafePointer: nil,
}
+var appenderMap sync.Map
+
func FieldAppender(dialect Dialect, field *Field) AppenderFunc {
if field.Tag.HasOption("msgpack") {
return appendMsgpack
@@ -59,10 +63,23 @@ func FieldAppender(dialect Dialect, field *Field) AppenderFunc {
return AppendJSONValue
}
- return dialect.Appender(field.StructField.Type)
+ return Appender(dialect, field.StructField.Type)
+}
+
+func Appender(dialect Dialect, typ reflect.Type) AppenderFunc {
+ if v, ok := appenderMap.Load(typ); ok {
+ return v.(AppenderFunc)
+ }
+
+ fn := appender(dialect, typ)
+
+ if v, ok := appenderMap.LoadOrStore(typ, fn); ok {
+ return v.(AppenderFunc)
+ }
+ return fn
}
-func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc {
+func appender(dialect Dialect, typ reflect.Type) AppenderFunc {
switch typ {
case bytesType:
return appendBytesValue
@@ -80,7 +97,7 @@ func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc {
return appendQueryAppenderValue
}
if typ.Implements(driverValuerType) {
- return driverValueAppender(custom)
+ return appendDriverValue
}
kind := typ.Kind()
@@ -88,18 +105,18 @@ func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc {
if kind != reflect.Ptr {
ptr := reflect.PtrTo(typ)
if ptr.Implements(queryAppenderType) {
- return addrAppender(appendQueryAppenderValue, custom)
+ return addrAppender(appendQueryAppenderValue)
}
if ptr.Implements(driverValuerType) {
- return addrAppender(driverValueAppender(custom), custom)
+ return addrAppender(appendDriverValue)
}
}
switch kind {
case reflect.Interface:
- return ifaceAppenderFunc(typ, custom)
+ return ifaceAppenderFunc
case reflect.Ptr:
- if fn := Appender(typ.Elem(), custom); fn != nil {
+ if fn := Appender(dialect, typ.Elem()); fn != nil {
return PtrAppender(fn)
}
case reflect.Slice:
@@ -112,23 +129,16 @@ func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc {
}
}
- if custom != nil {
- if fn := custom(typ); fn != nil {
- return fn
- }
- }
return appenders[typ.Kind()]
}
-func ifaceAppenderFunc(typ reflect.Type, custom func(reflect.Type) AppenderFunc) AppenderFunc {
- return func(fmter Formatter, b []byte, v reflect.Value) []byte {
- if v.IsNil() {
- return dialect.AppendNull(b)
- }
- elem := v.Elem()
- appender := Appender(elem.Type(), custom)
- return appender(fmter, b, elem)
+func ifaceAppenderFunc(fmter Formatter, b []byte, v reflect.Value) []byte {
+ if v.IsNil() {
+ return dialect.AppendNull(b)
}
+ elem := v.Elem()
+ appender := Appender(fmter.Dialect(), elem.Type())
+ return appender(fmter, b, elem)
}
func PtrAppender(fn AppenderFunc) AppenderFunc {
@@ -152,6 +162,14 @@ func AppendUintValue(fmter Formatter, b []byte, v reflect.Value) []byte {
return strconv.AppendUint(b, v.Uint(), 10)
}
+func appendUint32Value(fmter Formatter, b []byte, v reflect.Value) []byte {
+ return fmter.Dialect().AppendUint32(b, uint32(v.Uint()))
+}
+
+func appendUint64Value(fmter Formatter, b []byte, v reflect.Value) []byte {
+ return fmter.Dialect().AppendUint64(b, v.Uint())
+}
+
func AppendFloat32Value(fmter Formatter, b []byte, v reflect.Value) []byte {
return dialect.AppendFloat32(b, float32(v.Float()))
}
@@ -161,17 +179,17 @@ func AppendFloat64Value(fmter Formatter, b []byte, v reflect.Value) []byte {
}
func appendBytesValue(fmter Formatter, b []byte, v reflect.Value) []byte {
- return dialect.AppendBytes(b, v.Bytes())
+ return fmter.Dialect().AppendBytes(b, v.Bytes())
}
func appendArrayBytesValue(fmter Formatter, b []byte, v reflect.Value) []byte {
if v.CanAddr() {
- return dialect.AppendBytes(b, v.Slice(0, v.Len()).Bytes())
+ return fmter.Dialect().AppendBytes(b, v.Slice(0, v.Len()).Bytes())
}
tmp := make([]byte, v.Len())
reflect.Copy(reflect.ValueOf(tmp), v)
- b = dialect.AppendBytes(b, tmp)
+ b = fmter.Dialect().AppendBytes(b, tmp)
return b
}
@@ -189,12 +207,12 @@ func AppendJSONValue(fmter Formatter, b []byte, v reflect.Value) []byte {
bb = bb[:len(bb)-1]
}
- return dialect.AppendJSON(b, bb)
+ return fmter.Dialect().AppendJSON(b, bb)
}
func appendTimeValue(fmter Formatter, b []byte, v reflect.Value) []byte {
tm := v.Interface().(time.Time)
- return dialect.AppendTime(b, tm)
+ return fmter.Dialect().AppendTime(b, tm)
}
func appendIPValue(fmter Formatter, b []byte, v reflect.Value) []byte {
@@ -219,21 +237,15 @@ func appendQueryAppenderValue(fmter Formatter, b []byte, v reflect.Value) []byte
return AppendQueryAppender(fmter, b, v.Interface().(QueryAppender))
}
-func driverValueAppender(custom CustomAppender) AppenderFunc {
- return func(fmter Formatter, b []byte, v reflect.Value) []byte {
- return appendDriverValue(fmter, b, v.Interface().(driver.Valuer), custom)
- }
-}
-
-func appendDriverValue(fmter Formatter, b []byte, v driver.Valuer, custom CustomAppender) []byte {
- value, err := v.Value()
+func appendDriverValue(fmter Formatter, b []byte, v reflect.Value) []byte {
+ value, err := v.Interface().(driver.Valuer).Value()
if err != nil {
return dialect.AppendError(b, err)
}
- return Append(fmter, b, value, custom)
+ return Append(fmter, b, value)
}
-func addrAppender(fn AppenderFunc, custom CustomAppender) AppenderFunc {
+func addrAppender(fn AppenderFunc) AppenderFunc {
return func(fmter Formatter, b []byte, v reflect.Value) []byte {
if !v.CanAddr() {
err := fmt.Errorf("bun: Append(nonaddressable %T)", v.Interface())
@@ -242,3 +254,29 @@ func addrAppender(fn AppenderFunc, custom CustomAppender) AppenderFunc {
return fn(fmter, b, v.Addr())
}
}
+
+func appendMsgpack(fmter Formatter, b []byte, v reflect.Value) []byte {
+ hexEnc := internal.NewHexEncoder(b)
+
+ enc := msgpack.GetEncoder()
+ defer msgpack.PutEncoder(enc)
+
+ enc.Reset(hexEnc)
+ if err := enc.EncodeValue(v); err != nil {
+ return dialect.AppendError(b, err)
+ }
+
+ if err := hexEnc.Close(); err != nil {
+ return dialect.AppendError(b, err)
+ }
+
+ return hexEnc.Bytes()
+}
+
+func AppendQueryAppender(fmter Formatter, b []byte, app QueryAppender) []byte {
+ bb, err := app.AppendQuery(fmter, b)
+ if err != nil {
+ return dialect.AppendError(b, err)
+ }
+ return bb
+}