Vendor packages update

This commit is contained in:
2025-12-19 22:27:20 +02:00
parent 79effe6921
commit d9225a7310
196 changed files with 28595 additions and 1 deletions

81
vendor/github.com/uptrace/bun/schema/append.go generated vendored Normal file
View File

@@ -0,0 +1,81 @@
package schema
import (
"fmt"
"reflect"
"github.com/uptrace/bun/dialect"
)
func In(slice any) QueryAppender {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return &inValues{
err: fmt.Errorf("bun: In(non-slice %T)", slice),
}
}
return &inValues{
slice: v,
}
}
type inValues struct {
slice reflect.Value
err error
}
var _ QueryAppender = (*inValues)(nil)
func (in *inValues) AppendQuery(gen QueryGen, b []byte) (_ []byte, err error) {
if in.err != nil {
return nil, in.err
}
return appendIn(gen, b, in.slice), nil
}
func appendIn(gen QueryGen, b []byte, slice reflect.Value) []byte {
sliceLen := slice.Len()
if sliceLen == 0 {
return dialect.AppendNull(b)
}
for i := 0; i < sliceLen; i++ {
if i > 0 {
b = append(b, ", "...)
}
elem := slice.Index(i)
if elem.Kind() == reflect.Interface {
elem = elem.Elem()
}
if elem.Kind() == reflect.Slice && elem.Type() != bytesType {
b = append(b, '(')
b = appendIn(gen, b, elem)
b = append(b, ')')
} else {
b = gen.AppendValue(b, elem)
}
}
return b
}
//------------------------------------------------------------------------------
func NullZero(value any) QueryAppender {
return nullZero{
value: value,
}
}
type nullZero struct {
value any
}
func (nz nullZero) AppendQuery(gen QueryGen, b []byte) (_ []byte, err error) {
if isZero(nz.value) {
return dialect.AppendNull(b), nil
}
return gen.AppendValue(b, reflect.ValueOf(nz.value)), nil
}

316
vendor/github.com/uptrace/bun/schema/append_value.go generated vendored Normal file
View File

@@ -0,0 +1,316 @@
package schema
import (
"database/sql/driver"
"fmt"
"net"
"reflect"
"strconv"
"strings"
"time"
"github.com/puzpuzpuz/xsync/v3"
"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 (
AppenderFunc func(gen QueryGen, b []byte, v reflect.Value) []byte
CustomAppender func(typ reflect.Type) AppenderFunc
)
var appenders = []AppenderFunc{
reflect.Bool: AppendBoolValue,
reflect.Int: AppendIntValue,
reflect.Int8: AppendIntValue,
reflect.Int16: AppendIntValue,
reflect.Int32: AppendIntValue,
reflect.Int64: AppendIntValue,
reflect.Uint: AppendUintValue,
reflect.Uint8: AppendUintValue,
reflect.Uint16: AppendUintValue,
reflect.Uint32: appendUint32Value,
reflect.Uint64: appendUint64Value,
reflect.Uintptr: nil,
reflect.Float32: AppendFloat32Value,
reflect.Float64: AppendFloat64Value,
reflect.Complex64: nil,
reflect.Complex128: nil,
reflect.Array: AppendJSONValue,
reflect.Chan: nil,
reflect.Func: nil,
reflect.Interface: nil,
reflect.Map: AppendJSONValue,
reflect.Ptr: nil,
reflect.Slice: AppendJSONValue,
reflect.String: AppendStringValue,
reflect.Struct: AppendJSONValue,
reflect.UnsafePointer: nil,
}
var appenderCache = xsync.NewMapOf[reflect.Type, AppenderFunc]()
func FieldAppender(dialect Dialect, field *Field) AppenderFunc {
if field.Tag.HasOption("msgpack") {
return appendMsgpack
}
fieldType := field.StructField.Type
switch strings.ToUpper(field.UserSQLType) {
case sqltype.JSON, sqltype.JSONB:
if fieldType.Implements(driverValuerType) {
return appendDriverValue
}
if fieldType.Kind() != reflect.Ptr {
if reflect.PointerTo(fieldType).Implements(driverValuerType) {
return addrAppender(appendDriverValue)
}
}
return AppendJSONValue
}
return Appender(dialect, fieldType)
}
func Appender(dialect Dialect, typ reflect.Type) AppenderFunc {
if v, ok := appenderCache.Load(typ); ok {
return v
}
fn := appender(dialect, typ)
if v, ok := appenderCache.LoadOrStore(typ, fn); ok {
return v
}
return fn
}
func appender(dialect Dialect, typ reflect.Type) AppenderFunc {
switch typ {
case bytesType:
return appendBytesValue
case timeType:
return appendTimeValue
case timePtrType:
return PtrAppender(appendTimeValue)
case ipNetType:
return appendIPNetValue
case ipType, netipPrefixType, netipAddrType:
return appendStringer
case jsonRawMessageType:
return appendJSONRawMessageValue
}
kind := typ.Kind()
if typ.Implements(queryAppenderType) {
if kind == reflect.Ptr {
return nilAwareAppender(appendQueryAppenderValue)
}
return appendQueryAppenderValue
}
if typ.Implements(driverValuerType) {
if kind == reflect.Ptr {
return nilAwareAppender(appendDriverValue)
}
return appendDriverValue
}
if kind != reflect.Ptr {
ptr := reflect.PointerTo(typ)
if ptr.Implements(queryAppenderType) {
return addrAppender(appendQueryAppenderValue)
}
if ptr.Implements(driverValuerType) {
return addrAppender(appendDriverValue)
}
}
switch kind {
case reflect.Interface:
return ifaceAppenderFunc
case reflect.Ptr:
if typ.Implements(jsonMarshalerType) {
return nilAwareAppender(AppendJSONValue)
}
if fn := Appender(dialect, typ.Elem()); fn != nil {
return PtrAppender(fn)
}
case reflect.Slice:
if typ.Elem().Kind() == reflect.Uint8 {
return appendBytesValue
}
case reflect.Array:
if typ.Elem().Kind() == reflect.Uint8 {
return appendArrayBytesValue
}
}
return appenders[typ.Kind()]
}
func ifaceAppenderFunc(gen QueryGen, b []byte, v reflect.Value) []byte {
if v.IsNil() {
return dialect.AppendNull(b)
}
elem := v.Elem()
appender := Appender(gen.Dialect(), elem.Type())
return appender(gen, b, elem)
}
func nilAwareAppender(fn AppenderFunc) AppenderFunc {
return func(gen QueryGen, b []byte, v reflect.Value) []byte {
if v.IsNil() {
return dialect.AppendNull(b)
}
return fn(gen, b, v)
}
}
func PtrAppender(fn AppenderFunc) AppenderFunc {
return func(gen QueryGen, b []byte, v reflect.Value) []byte {
if v.IsNil() {
return dialect.AppendNull(b)
}
return fn(gen, b, v.Elem())
}
}
func AppendBoolValue(gen QueryGen, b []byte, v reflect.Value) []byte {
return gen.Dialect().AppendBool(b, v.Bool())
}
func AppendIntValue(gen QueryGen, b []byte, v reflect.Value) []byte {
return strconv.AppendInt(b, v.Int(), 10)
}
func AppendUintValue(gen QueryGen, b []byte, v reflect.Value) []byte {
return strconv.AppendUint(b, v.Uint(), 10)
}
func appendUint32Value(gen QueryGen, b []byte, v reflect.Value) []byte {
return gen.Dialect().AppendUint32(b, uint32(v.Uint()))
}
func appendUint64Value(gen QueryGen, b []byte, v reflect.Value) []byte {
return gen.Dialect().AppendUint64(b, v.Uint())
}
func AppendFloat32Value(gen QueryGen, b []byte, v reflect.Value) []byte {
return dialect.AppendFloat32(b, float32(v.Float()))
}
func AppendFloat64Value(gen QueryGen, b []byte, v reflect.Value) []byte {
return dialect.AppendFloat64(b, float64(v.Float()))
}
func appendBytesValue(gen QueryGen, b []byte, v reflect.Value) []byte {
return gen.Dialect().AppendBytes(b, v.Bytes())
}
func appendArrayBytesValue(gen QueryGen, b []byte, v reflect.Value) []byte {
if v.CanAddr() {
return gen.Dialect().AppendBytes(b, v.Slice(0, v.Len()).Bytes())
}
tmp := make([]byte, v.Len())
reflect.Copy(reflect.ValueOf(tmp), v)
b = gen.Dialect().AppendBytes(b, tmp)
return b
}
func AppendStringValue(gen QueryGen, b []byte, v reflect.Value) []byte {
return gen.Dialect().AppendString(b, v.String())
}
func AppendJSONValue(gen QueryGen, b []byte, v reflect.Value) []byte {
bb, err := bunjson.Marshal(v.Interface())
if err != nil {
return dialect.AppendError(b, err)
}
if len(bb) > 0 && bb[len(bb)-1] == '\n' {
bb = bb[:len(bb)-1]
}
return gen.Dialect().AppendJSON(b, bb)
}
func appendTimeValue(gen QueryGen, b []byte, v reflect.Value) []byte {
tm := v.Interface().(time.Time)
return gen.Dialect().AppendTime(b, tm)
}
func appendIPNetValue(gen QueryGen, b []byte, v reflect.Value) []byte {
ipnet := v.Interface().(net.IPNet)
return gen.Dialect().AppendString(b, ipnet.String())
}
func appendStringer(gen QueryGen, b []byte, v reflect.Value) []byte {
return gen.Dialect().AppendString(b, v.Interface().(fmt.Stringer).String())
}
func appendJSONRawMessageValue(gen QueryGen, b []byte, v reflect.Value) []byte {
bytes := v.Bytes()
if bytes == nil {
return dialect.AppendNull(b)
}
return gen.Dialect().AppendString(b, internal.String(bytes))
}
func appendQueryAppenderValue(gen QueryGen, b []byte, v reflect.Value) []byte {
return AppendQueryAppender(gen, b, v.Interface().(QueryAppender))
}
func appendDriverValue(gen QueryGen, b []byte, v reflect.Value) []byte {
value, err := v.Interface().(driver.Valuer).Value()
if err != nil {
return dialect.AppendError(b, err)
}
if _, ok := value.(driver.Valuer); ok {
return dialect.AppendError(b, fmt.Errorf("driver.Valuer returns unsupported type %T", value))
}
return gen.Append(b, value)
}
func addrAppender(fn AppenderFunc) AppenderFunc {
return func(gen QueryGen, b []byte, v reflect.Value) []byte {
if !v.CanAddr() {
err := fmt.Errorf("bun: Append(nonaddressable %T)", v.Interface())
return dialect.AppendError(b, err)
}
return fn(gen, b, v.Addr())
}
}
func appendMsgpack(gen QueryGen, 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(gen QueryGen, b []byte, app QueryAppender) []byte {
bb, err := app.AppendQuery(gen, b)
if err != nil {
return dialect.AppendError(b, err)
}
return bb
}

194
vendor/github.com/uptrace/bun/schema/dialect.go generated vendored Normal file
View File

@@ -0,0 +1,194 @@
package schema
import (
"database/sql"
"encoding/hex"
"strconv"
"time"
"unicode/utf8"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal/parser"
)
type Dialect interface {
Init(db *sql.DB)
Name() dialect.Name
Features() feature.Feature
Tables() *Tables
OnTable(table *Table)
IdentQuote() byte
AppendUint32(b []byte, n uint32) []byte
AppendUint64(b []byte, n uint64) []byte
AppendTime(b []byte, tm time.Time) []byte
AppendString(b []byte, s string) []byte
AppendBytes(b []byte, bs []byte) []byte
AppendJSON(b, jsonb []byte) []byte
AppendBool(b []byte, v bool) []byte
// AppendSequence adds the appropriate instruction for the driver to create a sequence
// from which (autoincremented) values for the column will be generated.
AppendSequence(b []byte, t *Table, f *Field) []byte
// DefaultVarcharLen should be returned for dialects in which specifying VARCHAR length
// is mandatory in queries that modify the schema (CREATE TABLE / ADD COLUMN, etc).
// Dialects that do not have such requirement may return 0, which should be interpreted so by the caller.
DefaultVarcharLen() int
// DefaultSchema should returns the name of the default database schema.
DefaultSchema() string
}
// ------------------------------------------------------------------------------
type BaseDialect struct{}
func (BaseDialect) AppendUint32(b []byte, n uint32) []byte {
return strconv.AppendUint(b, uint64(n), 10)
}
func (BaseDialect) AppendUint64(b []byte, n uint64) []byte {
return strconv.AppendUint(b, n, 10)
}
func (BaseDialect) AppendTime(b []byte, tm time.Time) []byte {
b = append(b, '\'')
b = tm.UTC().AppendFormat(b, "2006-01-02 15:04:05.999999-07:00")
b = append(b, '\'')
return b
}
func (BaseDialect) AppendString(b []byte, s string) []byte {
b = append(b, '\'')
for _, r := range s {
if r == '\000' {
continue
}
if r == '\'' {
b = append(b, '\'', '\'')
continue
}
if r < utf8.RuneSelf {
b = append(b, byte(r))
continue
}
l := len(b)
if cap(b)-l < utf8.UTFMax {
b = append(b, make([]byte, utf8.UTFMax)...)
}
n := utf8.EncodeRune(b[l:l+utf8.UTFMax], r)
b = b[:l+n]
}
b = append(b, '\'')
return b
}
func (BaseDialect) AppendBytes(b, bs []byte) []byte {
if bs == nil {
return dialect.AppendNull(b)
}
b = append(b, `'\x`...)
s := len(b)
b = append(b, make([]byte, hex.EncodedLen(len(bs)))...)
hex.Encode(b[s:], bs)
b = append(b, '\'')
return b
}
func (BaseDialect) AppendJSON(b, jsonb []byte) []byte {
b = append(b, '\'')
p := parser.New(jsonb)
for p.Valid() {
c := p.Read()
switch c {
case '"':
b = append(b, '"')
case '\'':
b = append(b, "''"...)
case '\000':
continue
case '\\':
if p.CutPrefix([]byte("u0000")) {
b = append(b, `\\u0000`...)
} else {
b = append(b, '\\')
if p.Valid() {
b = append(b, p.Read())
}
}
default:
b = append(b, c)
}
}
b = append(b, '\'')
return b
}
func (BaseDialect) AppendBool(b []byte, v bool) []byte {
return dialect.AppendBool(b, v)
}
// ------------------------------------------------------------------------------
type nopDialect struct {
BaseDialect
tables *Tables
features feature.Feature
}
func newNopDialect() *nopDialect {
d := new(nopDialect)
d.tables = NewTables(d)
d.features = feature.Returning
return d
}
func (d *nopDialect) Init(*sql.DB) {}
func (d *nopDialect) Name() dialect.Name {
return dialect.Invalid
}
func (d *nopDialect) Features() feature.Feature {
return d.features
}
func (d *nopDialect) Tables() *Tables {
return d.tables
}
func (d *nopDialect) OnField(field *Field) {}
func (d *nopDialect) OnTable(table *Table) {}
func (d *nopDialect) IdentQuote() byte {
return '"'
}
func (d *nopDialect) DefaultVarcharLen() int {
return 0
}
func (d *nopDialect) AppendSequence(b []byte, _ *Table, _ *Field) []byte {
return b
}
func (d *nopDialect) DefaultSchema() string {
return "nop"
}

137
vendor/github.com/uptrace/bun/schema/field.go generated vendored Normal file
View File

@@ -0,0 +1,137 @@
package schema
import (
"fmt"
"reflect"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/internal"
"github.com/uptrace/bun/internal/tagparser"
)
type Field struct {
Table *Table // Contains this field
StructField reflect.StructField
IsPtr bool
Tag tagparser.Tag
IndirectType reflect.Type
Index []int
Name string // SQL name, .e.g. id
SQLName Safe // escaped SQL name, e.g. "id"
GoName string // struct field name, e.g. Id
DiscoveredSQLType string
UserSQLType string
CreateTableSQLType string
SQLDefault string
OnDelete string
OnUpdate string
IsPK bool
NotNull bool
NullZero bool
AutoIncrement bool
Identity bool
Append AppenderFunc
Scan ScannerFunc
IsZero IsZeroerFunc
}
func (f *Field) String() string {
return f.Name
}
func (f *Field) WithIndex(path []int) *Field {
if len(path) == 0 {
return f
}
clone := *f
clone.Index = makeIndex(path, f.Index)
return &clone
}
func (f *Field) Clone() *Field {
cp := *f
cp.Index = cp.Index[:len(f.Index):len(f.Index)]
return &cp
}
func (f *Field) Value(strct reflect.Value) reflect.Value {
return internal.FieldByIndexAlloc(strct, f.Index)
}
func (f *Field) HasNilValue(v reflect.Value) bool {
if len(f.Index) == 1 {
return v.Field(f.Index[0]).IsNil()
}
for _, index := range f.Index {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return true
}
v = v.Elem()
}
v = v.Field(index)
}
return v.IsNil()
}
func (f *Field) HasZeroValue(v reflect.Value) bool {
if len(f.Index) == 1 {
return f.IsZero(v.Field(f.Index[0]))
}
for _, index := range f.Index {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return true
}
v = v.Elem()
}
v = v.Field(index)
}
return f.IsZero(v)
}
func (f *Field) AppendValue(gen QueryGen, b []byte, strct reflect.Value) []byte {
fv, ok := fieldByIndex(strct, f.Index)
if !ok {
return dialect.AppendNull(b)
}
if (f.IsPtr && fv.IsNil()) || (f.NullZero && f.IsZero(fv)) {
return dialect.AppendNull(b)
}
if f.Append == nil {
panic(fmt.Errorf("bun: AppendValue(unsupported %s)", fv.Type()))
}
return f.Append(gen, b, fv)
}
func (f *Field) ScanValue(strct reflect.Value, src any) error {
if src == nil {
if fv, ok := fieldByIndex(strct, f.Index); ok {
return f.ScanWithCheck(fv, src)
}
return nil
}
fv := internal.FieldByIndexAlloc(strct, f.Index)
return f.ScanWithCheck(fv, src)
}
func (f *Field) ScanWithCheck(fv reflect.Value, src any) error {
if f.Scan == nil {
return fmt.Errorf("bun: Scan(unsupported %s)", f.IndirectType)
}
return f.Scan(fv, src)
}
func (f *Field) SkipUpdate() bool {
return f.Tag.HasOption("skipupdate")
}

43
vendor/github.com/uptrace/bun/schema/hook.go generated vendored Normal file
View File

@@ -0,0 +1,43 @@
package schema
import (
"context"
"database/sql"
"reflect"
)
type Model interface {
ScanRows(ctx context.Context, rows *sql.Rows) (int, error)
Value() any
}
type Query interface {
QueryAppender
Operation() string
GetModel() Model
GetTableName() string
}
//------------------------------------------------------------------------------
type BeforeAppendModelHook interface {
BeforeAppendModel(ctx context.Context, query Query) error
}
var beforeAppendModelHookType = reflect.TypeFor[BeforeAppendModelHook]()
//------------------------------------------------------------------------------
type BeforeScanRowHook interface {
BeforeScanRow(context.Context) error
}
var beforeScanRowHookType = reflect.TypeFor[BeforeScanRowHook]()
//------------------------------------------------------------------------------
type AfterScanRowHook interface {
AfterScanRow(context.Context) error
}
var afterScanRowHookType = reflect.TypeFor[AfterScanRowHook]()

291
vendor/github.com/uptrace/bun/schema/querygen.go generated vendored Normal file
View File

@@ -0,0 +1,291 @@
package schema
import (
"reflect"
"strconv"
"strings"
"time"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal"
"github.com/uptrace/bun/internal/parser"
)
var nopQueryGen = QueryGen{
dialect: newNopDialect(),
}
type QueryGen struct {
dialect Dialect
args *namedArgList
}
func NewQueryGen(dialect Dialect) QueryGen {
return QueryGen{
dialect: dialect,
}
}
func NewNopQueryGen() QueryGen {
return nopQueryGen
}
func (f QueryGen) IsNop() bool {
return f.dialect.Name() == dialect.Invalid
}
func (f QueryGen) Dialect() Dialect {
return f.dialect
}
func (f QueryGen) IdentQuote() byte {
return f.dialect.IdentQuote()
}
func (gen QueryGen) Append(b []byte, v any) []byte {
switch v := v.(type) {
case nil:
return dialect.AppendNull(b)
case bool:
return dialect.AppendBool(b, v)
case int:
return strconv.AppendInt(b, int64(v), 10)
case int32:
return strconv.AppendInt(b, int64(v), 10)
case int64:
return strconv.AppendInt(b, v, 10)
case uint:
return strconv.AppendInt(b, int64(v), 10)
case uint32:
return gen.Dialect().AppendUint32(b, v)
case uint64:
return gen.Dialect().AppendUint64(b, v)
case float32:
return dialect.AppendFloat32(b, v)
case float64:
return dialect.AppendFloat64(b, v)
case string:
return gen.Dialect().AppendString(b, v)
case time.Time:
return gen.Dialect().AppendTime(b, v)
case []byte:
return gen.Dialect().AppendBytes(b, v)
case QueryAppender:
return AppendQueryAppender(gen, b, v)
default:
vv := reflect.ValueOf(v)
if vv.Kind() == reflect.Ptr && vv.IsNil() {
return dialect.AppendNull(b)
}
appender := Appender(gen.Dialect(), vv.Type())
return appender(gen, b, vv)
}
}
func (f QueryGen) AppendName(b []byte, name string) []byte {
return dialect.AppendName(b, name, f.IdentQuote())
}
func (f QueryGen) AppendIdent(b []byte, ident string) []byte {
return dialect.AppendIdent(b, ident, f.IdentQuote())
}
func (f QueryGen) AppendValue(b []byte, v reflect.Value) []byte {
if v.Kind() == reflect.Ptr && v.IsNil() {
return dialect.AppendNull(b)
}
appender := Appender(f.dialect, v.Type())
return appender(f, b, v)
}
func (f QueryGen) HasFeature(feature feature.Feature) bool {
return f.dialect.Features().Has(feature)
}
func (f QueryGen) WithArg(arg NamedArgAppender) QueryGen {
return QueryGen{
dialect: f.dialect,
args: f.args.WithArg(arg),
}
}
func (f QueryGen) WithNamedArg(name string, value any) QueryGen {
return QueryGen{
dialect: f.dialect,
args: f.args.WithArg(&namedArg{name: name, value: value}),
}
}
func (f QueryGen) FormatQuery(query string, args ...any) string {
if f.IsNop() || (args == nil && f.args == nil) || strings.IndexByte(query, '?') == -1 {
return query
}
return internal.String(f.AppendQuery(nil, query, args...))
}
func (f QueryGen) AppendQuery(dst []byte, query string, args ...any) []byte {
if f.IsNop() || (args == nil && f.args == nil) || strings.IndexByte(query, '?') == -1 {
return append(dst, query...)
}
return f.append(dst, parser.NewString(query), args)
}
func (f QueryGen) append(dst []byte, p *parser.Parser, args []any) []byte {
var namedArgs NamedArgAppender
if len(args) == 1 {
if v, ok := args[0].(NamedArgAppender); ok {
namedArgs = v
} else if v, ok := newStructArgs(f, args[0]); ok {
namedArgs = v
}
}
var argIndex int
for p.Valid() {
b, ok := p.ReadSep('?')
if !ok {
dst = append(dst, b...)
continue
}
if len(b) > 0 && b[len(b)-1] == '\\' {
dst = append(dst, b[:len(b)-1]...)
dst = append(dst, '?')
continue
}
dst = append(dst, b...)
name, numeric := p.ReadIdentifier()
if name != "" {
if numeric {
idx, err := strconv.Atoi(name)
if err != nil {
goto restore_arg
}
if idx >= len(args) {
goto restore_arg
}
dst = f.appendArg(dst, args[idx])
continue
}
if namedArgs != nil {
dst, ok = namedArgs.AppendNamedArg(f, dst, name)
if ok {
continue
}
}
dst, ok = f.args.AppendNamedArg(f, dst, name)
if ok {
continue
}
restore_arg:
dst = append(dst, '?')
dst = append(dst, name...)
continue
}
if argIndex >= len(args) {
dst = append(dst, '?')
continue
}
arg := args[argIndex]
argIndex++
dst = f.appendArg(dst, arg)
}
return dst
}
func (gen QueryGen) appendArg(b []byte, arg any) []byte {
switch arg := arg.(type) {
case QueryAppender:
bb, err := arg.AppendQuery(gen, b)
if err != nil {
return dialect.AppendError(b, err)
}
return bb
default:
return gen.Append(b, arg)
}
}
//------------------------------------------------------------------------------
type NamedArgAppender interface {
AppendNamedArg(gen QueryGen, b []byte, name string) ([]byte, bool)
}
type namedArgList struct {
arg NamedArgAppender
next *namedArgList
}
func (l *namedArgList) WithArg(arg NamedArgAppender) *namedArgList {
return &namedArgList{
arg: arg,
next: l,
}
}
func (l *namedArgList) AppendNamedArg(gen QueryGen, b []byte, name string) ([]byte, bool) {
for l != nil && l.arg != nil {
if b, ok := l.arg.AppendNamedArg(gen, b, name); ok {
return b, true
}
l = l.next
}
return b, false
}
//------------------------------------------------------------------------------
type namedArg struct {
name string
value any
}
var _ NamedArgAppender = (*namedArg)(nil)
func (a *namedArg) AppendNamedArg(gen QueryGen, b []byte, name string) ([]byte, bool) {
if a.name == name {
return gen.appendArg(b, a.value), true
}
return b, false
}
//------------------------------------------------------------------------------
type structArgs struct {
table *Table
strct reflect.Value
}
var _ NamedArgAppender = (*structArgs)(nil)
func newStructArgs(gen QueryGen, strct any) (*structArgs, bool) {
v := reflect.ValueOf(strct)
if !v.IsValid() {
return nil, false
}
v = reflect.Indirect(v)
if v.Kind() != reflect.Struct {
return nil, false
}
return &structArgs{
table: gen.Dialect().Tables().Get(v.Type()),
strct: v,
}, true
}
func (m *structArgs) AppendNamedArg(gen QueryGen, b []byte, name string) ([]byte, bool) {
return m.table.AppendNamedArg(gen, b, name, m.strct)
}

51
vendor/github.com/uptrace/bun/schema/reflect.go generated vendored Normal file
View File

@@ -0,0 +1,51 @@
package schema
import (
"database/sql/driver"
"encoding/json"
"net"
"net/netip"
"reflect"
"time"
)
var (
bytesType = reflect.TypeFor[[]byte]()
timePtrType = reflect.TypeFor[*time.Time]()
timeType = reflect.TypeFor[time.Time]()
ipType = reflect.TypeFor[net.IP]()
ipNetType = reflect.TypeFor[net.IPNet]()
netipPrefixType = reflect.TypeFor[netip.Prefix]()
netipAddrType = reflect.TypeFor[netip.Addr]()
jsonRawMessageType = reflect.TypeFor[json.RawMessage]()
driverValuerType = reflect.TypeFor[driver.Valuer]()
queryAppenderType = reflect.TypeFor[QueryAppender]()
jsonMarshalerType = reflect.TypeFor[json.Marshaler]()
)
func indirectType(t reflect.Type) reflect.Type {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
return t
}
func fieldByIndex(v reflect.Value, index []int) (_ reflect.Value, ok bool) {
if len(index) == 1 {
return v.Field(index[0]), true
}
for i, idx := range index {
if i > 0 {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return v, false
}
v = v.Elem()
}
}
v = v.Field(idx)
}
return v, true
}

84
vendor/github.com/uptrace/bun/schema/relation.go generated vendored Normal file
View File

@@ -0,0 +1,84 @@
package schema
import (
"fmt"
)
const (
InvalidRelation = iota
HasOneRelation
BelongsToRelation
HasManyRelation
ManyToManyRelation
)
type Relation struct {
Type int
Field *Field // Has the bun tag defining this relation.
// Base and Join can be explained with this query:
//
// SELECT * FROM base_table JOIN join_table
JoinTable *Table
BasePKs []*Field
JoinPKs []*Field
OnUpdate string
OnDelete string
Condition []string
PolymorphicField *Field
PolymorphicValue string
M2MTable *Table
M2MBasePKs []*Field
M2MJoinPKs []*Field
}
// References returns true if the table which defines this Relation
// needs to declare a foreign key constraint, as is the case
// for 'has-one' and 'belongs-to' relations. For other relations,
// the constraint is created either in the referencing table (1:N, 'has-many' relations)
// or the junction table (N:N, 'm2m' relations).
//
// Usage of `rel:` tag does not always imply creation of foreign keys (when WithForeignKeys() is not set)
// and can be used exclusively for joining tables at query time. For example:
//
// type User struct {
// ID int64 `bun:",pk"`
// Profile *Profile `bun:",rel:has-one,join:id=user_id"`
// }
//
// Creating a FK users.id -> profiles.user_id would be confusing and incorrect,
// so for such cases References() returns false. One notable exception to this rule
// is when a Relation is defined in a junction table, in which case it is perfectly
// fine for its primary keys to reference other tables. Consider:
//
// // UsersToGroups maps users to groups they follow.
// type UsersToGroups struct {
// UserID string `bun:"user_id,pk"` // Needs FK to users.id
// GroupID string `bun:"group_id,pk"` // Needs FK to groups.id
//
// User *User `bun:"rel:belongs-to,join:user_id=id"`
// Group *Group `bun:"rel:belongs-to,join:group_id=id"`
// }
//
// Here BooksToReaders has a composite primary key, composed of other primary keys.
func (r *Relation) References() bool {
allPK := true
nonePK := true
for _, f := range r.BasePKs {
allPK = allPK && f.IsPK
nonePK = nonePK && !f.IsPK
}
// Erring on the side of caution, only create foreign keys
// if the referencing columns are part of a composite PK
// in the junction table of the m2m relationship.
effectsM2M := r.Field.Table.IsM2MTable && allPK
return (r.Type == HasOneRelation || r.Type == BelongsToRelation) && (effectsM2M || nonePK)
}
func (r *Relation) String() string {
return fmt.Sprintf("relation=%s", r.Field.GoName)
}

566
vendor/github.com/uptrace/bun/schema/scan.go generated vendored Normal file
View File

@@ -0,0 +1,566 @@
package schema
import (
"bytes"
"database/sql"
"fmt"
"net"
"net/netip"
"reflect"
"strconv"
"strings"
"time"
"github.com/puzpuzpuz/xsync/v3"
"github.com/vmihailenco/msgpack/v5"
"github.com/uptrace/bun/dialect/sqltype"
"github.com/uptrace/bun/extra/bunjson"
"github.com/uptrace/bun/internal"
)
var scannerType = reflect.TypeFor[sql.Scanner]()
type ScannerFunc func(dest reflect.Value, src any) error
var scanners []ScannerFunc
func init() {
scanners = []ScannerFunc{
reflect.Bool: scanBool,
reflect.Int: scanInt64,
reflect.Int8: scanInt64,
reflect.Int16: scanInt64,
reflect.Int32: scanInt64,
reflect.Int64: scanInt64,
reflect.Uint: scanUint64,
reflect.Uint8: scanUint64,
reflect.Uint16: scanUint64,
reflect.Uint32: scanUint64,
reflect.Uint64: scanUint64,
reflect.Uintptr: scanUint64,
reflect.Float32: scanFloat,
reflect.Float64: scanFloat,
reflect.Complex64: nil,
reflect.Complex128: nil,
reflect.Array: nil,
reflect.Interface: scanInterface,
reflect.Map: scanJSON,
reflect.Ptr: nil,
reflect.Slice: scanJSON,
reflect.String: scanString,
reflect.Struct: scanJSON,
reflect.UnsafePointer: nil,
}
}
var scannerCache = xsync.NewMapOf[reflect.Type, ScannerFunc]()
func FieldScanner(dialect Dialect, field *Field) ScannerFunc {
if field.Tag.HasOption("msgpack") {
return scanMsgpack
}
if field.Tag.HasOption("json_use_number") {
return scanJSONUseNumber
}
if field.StructField.Type.Kind() == reflect.Interface {
switch strings.ToUpper(field.UserSQLType) {
case sqltype.JSON, sqltype.JSONB:
return scanJSONIntoInterface
}
}
return Scanner(field.StructField.Type)
}
func Scanner(typ reflect.Type) ScannerFunc {
if v, ok := scannerCache.Load(typ); ok {
return v
}
fn := scanner(typ)
if v, ok := scannerCache.LoadOrStore(typ, fn); ok {
return v
}
return fn
}
func scanner(typ reflect.Type) ScannerFunc {
kind := typ.Kind()
if kind == reflect.Ptr {
if fn := Scanner(typ.Elem()); fn != nil {
return PtrScanner(fn)
}
}
switch typ {
case bytesType:
return scanBytes
case timeType:
return scanTime
case ipType:
return scanIP
case ipNetType:
return scanIPNet
case netipAddrType:
return scanNetIpAddr
case netipPrefixType:
return scanNetIpPrefix
case jsonRawMessageType:
return scanBytes
}
if typ.Implements(scannerType) {
return scanScanner
}
if kind != reflect.Ptr {
ptr := reflect.PointerTo(typ)
if ptr.Implements(scannerType) {
return addrScanner(scanScanner)
}
}
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return scanBytes
}
return scanners[kind]
}
func scanBool(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
dest.SetBool(false)
return nil
case bool:
dest.SetBool(src)
return nil
case int64:
dest.SetBool(src != 0)
return nil
case []byte:
f, err := strconv.ParseBool(internal.String(src))
if err != nil {
return err
}
dest.SetBool(f)
return nil
case string:
f, err := strconv.ParseBool(src)
if err != nil {
return err
}
dest.SetBool(f)
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanInt64(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
dest.SetInt(0)
return nil
case int64:
dest.SetInt(src)
return nil
case uint64:
dest.SetInt(int64(src))
return nil
case []byte:
n, err := strconv.ParseInt(internal.String(src), 10, 64)
if err != nil {
return err
}
dest.SetInt(n)
return nil
case string:
n, err := strconv.ParseInt(src, 10, 64)
if err != nil {
return err
}
dest.SetInt(n)
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanUint64(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
dest.SetUint(0)
return nil
case uint64:
dest.SetUint(src)
return nil
case int64:
dest.SetUint(uint64(src))
return nil
case []byte:
n, err := strconv.ParseUint(internal.String(src), 10, 64)
if err != nil {
return err
}
dest.SetUint(n)
return nil
case string:
n, err := strconv.ParseUint(src, 10, 64)
if err != nil {
return err
}
dest.SetUint(n)
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanFloat(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
dest.SetFloat(0)
return nil
case float32:
dest.SetFloat(float64(src))
return nil
case float64:
dest.SetFloat(src)
return nil
case []byte:
f, err := strconv.ParseFloat(internal.String(src), 64)
if err != nil {
return err
}
dest.SetFloat(f)
return nil
case string:
f, err := strconv.ParseFloat(src, 64)
if err != nil {
return err
}
dest.SetFloat(f)
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanString(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
dest.SetString("")
return nil
case string:
dest.SetString(src)
return nil
case []byte:
dest.SetString(string(src))
return nil
case time.Time:
dest.SetString(src.Format(time.RFC3339Nano))
return nil
case int64:
dest.SetString(strconv.FormatInt(src, 10))
return nil
case uint64:
dest.SetString(strconv.FormatUint(src, 10))
return nil
case float64:
dest.SetString(strconv.FormatFloat(src, 'G', -1, 64))
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanBytes(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
dest.SetBytes(nil)
return nil
case string:
dest.SetBytes([]byte(src))
return nil
case []byte:
clone := make([]byte, len(src))
copy(clone, src)
dest.SetBytes(clone)
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanTime(dest reflect.Value, src any) error {
switch src := src.(type) {
case nil:
destTime := dest.Addr().Interface().(*time.Time)
*destTime = time.Time{}
return nil
case time.Time:
destTime := dest.Addr().Interface().(*time.Time)
*destTime = src
return nil
case string:
srcTime, err := internal.ParseTime(src)
if err != nil {
return err
}
destTime := dest.Addr().Interface().(*time.Time)
*destTime = srcTime
return nil
case []byte:
srcTime, err := internal.ParseTime(internal.String(src))
if err != nil {
return err
}
destTime := dest.Addr().Interface().(*time.Time)
*destTime = srcTime
return nil
default:
return scanError(dest.Type(), src)
}
}
func scanScanner(dest reflect.Value, src any) error {
return dest.Interface().(sql.Scanner).Scan(src)
}
func scanMsgpack(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
dec := msgpack.GetDecoder()
defer msgpack.PutDecoder(dec)
dec.Reset(bytes.NewReader(b))
return dec.DecodeValue(dest)
}
func scanJSON(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
return bunjson.Unmarshal(b, dest.Addr().Interface())
}
func scanJSONUseNumber(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
dec := bunjson.NewDecoder(bytes.NewReader(b))
dec.UseNumber()
return dec.Decode(dest.Addr().Interface())
}
func scanIP(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
ip := net.ParseIP(internal.String(b))
if ip == nil {
return fmt.Errorf("bun: invalid ip: %q", b)
}
ptr := dest.Addr().Interface().(*net.IP)
*ptr = ip
return nil
}
func scanIPNet(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
_, ipnet, err := net.ParseCIDR(internal.String(b))
if err != nil {
return err
}
ptr := dest.Addr().Interface().(*net.IPNet)
*ptr = *ipnet
return nil
}
func scanNetIpAddr(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
val, _ := netip.ParseAddr(internal.String(b))
if !val.IsValid() {
return fmt.Errorf("bun: invalid ip: %q", b)
}
ptr := dest.Addr().Interface().(*netip.Addr)
*ptr = val
return nil
}
func scanNetIpPrefix(dest reflect.Value, src any) error {
if src == nil {
return scanNull(dest)
}
b, err := toBytes(src)
if err != nil {
return err
}
val, _ := netip.ParsePrefix(internal.String(b))
if !val.IsValid() {
return fmt.Errorf("bun: invalid prefix: %q", b)
}
ptr := dest.Addr().Interface().(*netip.Prefix)
*ptr = val
return nil
}
func addrScanner(fn ScannerFunc) ScannerFunc {
return func(dest reflect.Value, src any) error {
if !dest.CanAddr() {
return fmt.Errorf("bun: Scan(nonaddressable %T)", dest.Interface())
}
return fn(dest.Addr(), src)
}
}
func toBytes(src any) ([]byte, error) {
switch src := src.(type) {
case string:
return internal.Bytes(src), nil
case []byte:
return src, nil
default:
return nil, fmt.Errorf("bun: got %T, wanted []byte or string", src)
}
}
func PtrScanner(fn ScannerFunc) ScannerFunc {
return func(dest reflect.Value, src any) error {
if src == nil {
if !dest.CanAddr() {
if dest.IsNil() {
return nil
}
return fn(dest.Elem(), src)
}
if !dest.IsNil() {
dest.Set(reflect.New(dest.Type().Elem()))
}
return nil
}
if dest.IsNil() {
dest.Set(reflect.New(dest.Type().Elem()))
}
if dest.Kind() == reflect.Map {
return fn(dest, src)
}
return fn(dest.Elem(), src)
}
}
func scanNull(dest reflect.Value) error {
if nilable(dest.Kind()) && dest.IsNil() {
return nil
}
dest.Set(reflect.New(dest.Type()).Elem())
return nil
}
func scanJSONIntoInterface(dest reflect.Value, src any) error {
if dest.IsNil() {
if src == nil {
return nil
}
b, err := toBytes(src)
if err != nil {
return err
}
return bunjson.Unmarshal(b, dest.Addr().Interface())
}
dest = dest.Elem()
if fn := Scanner(dest.Type()); fn != nil {
return fn(dest, src)
}
return scanError(dest.Type(), src)
}
func scanInterface(dest reflect.Value, src any) error {
if dest.IsNil() {
if src == nil {
return nil
}
dest.Set(reflect.ValueOf(src))
return nil
}
dest = dest.Elem()
if fn := Scanner(dest.Type()); fn != nil {
return fn(dest, src)
}
return scanError(dest.Type(), src)
}
func nilable(kind reflect.Kind) bool {
switch kind {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return true
}
return false
}
func scanError(dest reflect.Type, src any) error {
return fmt.Errorf("bun: can't scan %#v (%T) into %s", src, src, dest.String())
}

133
vendor/github.com/uptrace/bun/schema/sqlfmt.go generated vendored Normal file
View File

@@ -0,0 +1,133 @@
package schema
import (
"log/slog"
"strings"
"github.com/uptrace/bun/internal"
)
type QueryAppender interface {
AppendQuery(gen QueryGen, b []byte) ([]byte, error)
}
type ColumnsAppender interface {
AppendColumns(gen QueryGen, b []byte) ([]byte, error)
}
//------------------------------------------------------------------------------
// Safe represents a safe SQL query.
type Safe string
var _ QueryAppender = (*Safe)(nil)
func (s Safe) AppendQuery(gen QueryGen, b []byte) ([]byte, error) {
return append(b, s...), nil
}
//------------------------------------------------------------------------------
// Name represents a single SQL name, for example, a column name.
type Name string
var _ QueryAppender = (*Name)(nil)
func (s Name) AppendQuery(gen QueryGen, b []byte) ([]byte, error) {
return gen.AppendName(b, string(s)), nil
}
//------------------------------------------------------------------------------
// Ident represents a SQL identifier, for example,
// a fully qualified column name such as `table_name.col_name`.
type Ident string
var _ QueryAppender = (*Ident)(nil)
func (s Ident) AppendQuery(gen QueryGen, b []byte) ([]byte, error) {
return gen.AppendIdent(b, string(s)), nil
}
//------------------------------------------------------------------------------
// NOTE: It should not be modified after creation.
type QueryWithArgs struct {
Query string
Args []any
}
var _ QueryAppender = QueryWithArgs{}
func SafeQuery(query string, args []any) QueryWithArgs {
if args == nil {
args = make([]any, 0)
} else if len(query) > 0 && strings.IndexByte(query, '?') == -1 {
internal.Warn.Printf("query %q has %v args, but no placeholders", query, args)
}
return QueryWithArgs{
Query: query,
Args: args,
}
}
func UnsafeIdent(ident string) QueryWithArgs {
return QueryWithArgs{Query: ident}
}
func (q QueryWithArgs) IsZero() bool {
return q.Query == "" && q.Args == nil
}
func (q QueryWithArgs) AppendQuery(gen QueryGen, b []byte) ([]byte, error) {
if q.Args == nil {
return gen.AppendIdent(b, q.Query), nil
}
return gen.AppendQuery(b, q.Query, q.Args...), nil
}
//------------------------------------------------------------------------------
type Order string
const (
OrderNone Order = ""
OrderAsc Order = "ASC"
OrderAscNullsFirst Order = "ASC NULLS FIRST"
OrderAscNullsLast Order = "ASC NULLS LAST"
OrderDesc Order = "DESC"
OrderDescNullsFirst Order = "DESC NULLS FIRST"
OrderDescNullsLast Order = "DESC NULLS LAST"
)
func (s Order) AppendQuery(gen QueryGen, b []byte) ([]byte, error) {
return AppendOrder(b, s), nil
}
func AppendOrder(b []byte, sortDir Order) []byte {
switch sortDir {
case OrderAsc, OrderDesc,
OrderAscNullsFirst, OrderAscNullsLast,
OrderDescNullsFirst, OrderDescNullsLast:
return append(b, sortDir...)
case OrderNone:
return b
default:
slog.Error("unsupported sort direction", slog.String("sort_dir", string(sortDir)))
return b
}
}
//------------------------------------------------------------------------------
type QueryWithSep struct {
QueryWithArgs
Sep string
}
func SafeQueryWithSep(query string, args []any, sep string) QueryWithSep {
return QueryWithSep{
QueryWithArgs: SafeQuery(query, args),
Sep: sep,
}
}

141
vendor/github.com/uptrace/bun/schema/sqltype.go generated vendored Normal file
View File

@@ -0,0 +1,141 @@
package schema
import (
"bytes"
"database/sql"
"encoding/json"
"reflect"
"time"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/sqltype"
"github.com/uptrace/bun/internal"
)
var (
bunNullTimeType = reflect.TypeFor[NullTime]()
nullTimeType = reflect.TypeFor[sql.NullTime]()
nullBoolType = reflect.TypeFor[sql.NullBool]()
nullFloatType = reflect.TypeFor[sql.NullFloat64]()
nullIntType = reflect.TypeFor[sql.NullInt64]()
nullStringType = reflect.TypeFor[sql.NullString]()
)
var sqlTypes = []string{
reflect.Bool: sqltype.Boolean,
reflect.Int: sqltype.BigInt,
reflect.Int8: sqltype.SmallInt,
reflect.Int16: sqltype.SmallInt,
reflect.Int32: sqltype.Integer,
reflect.Int64: sqltype.BigInt,
reflect.Uint: sqltype.BigInt,
reflect.Uint8: sqltype.SmallInt,
reflect.Uint16: sqltype.SmallInt,
reflect.Uint32: sqltype.Integer,
reflect.Uint64: sqltype.BigInt,
reflect.Uintptr: sqltype.BigInt,
reflect.Float32: sqltype.Real,
reflect.Float64: sqltype.DoublePrecision,
reflect.Complex64: "",
reflect.Complex128: "",
reflect.Array: "",
reflect.Interface: "",
reflect.Map: sqltype.VarChar,
reflect.Ptr: "",
reflect.Slice: sqltype.VarChar,
reflect.String: sqltype.VarChar,
reflect.Struct: sqltype.VarChar,
}
func DiscoverSQLType(typ reflect.Type) string {
switch typ {
case timeType, nullTimeType, bunNullTimeType:
return sqltype.Timestamp
case nullBoolType:
return sqltype.Boolean
case nullFloatType:
return sqltype.DoublePrecision
case nullIntType:
return sqltype.BigInt
case nullStringType:
return sqltype.VarChar
case jsonRawMessageType:
return sqltype.JSON
}
switch typ.Kind() {
case reflect.Slice:
if typ.Elem().Kind() == reflect.Uint8 {
return sqltype.Blob
}
}
return sqlTypes[typ.Kind()]
}
//------------------------------------------------------------------------------
var jsonNull = []byte("null")
// NullTime is a time.Time wrapper that marshals zero time as JSON null and SQL NULL.
type NullTime struct {
time.Time
}
var (
_ json.Marshaler = (*NullTime)(nil)
_ json.Unmarshaler = (*NullTime)(nil)
_ sql.Scanner = (*NullTime)(nil)
_ QueryAppender = (*NullTime)(nil)
)
func (tm NullTime) MarshalJSON() ([]byte, error) {
if tm.IsZero() {
return jsonNull, nil
}
return tm.Time.MarshalJSON()
}
func (tm *NullTime) UnmarshalJSON(b []byte) error {
if bytes.Equal(b, jsonNull) {
tm.Time = time.Time{}
return nil
}
return tm.Time.UnmarshalJSON(b)
}
func (tm NullTime) AppendQuery(gen QueryGen, b []byte) ([]byte, error) {
if tm.IsZero() {
return dialect.AppendNull(b), nil
}
return gen.Dialect().AppendTime(b, tm.Time), nil
}
func (tm *NullTime) Scan(src any) error {
if src == nil {
tm.Time = time.Time{}
return nil
}
switch src := src.(type) {
case time.Time:
tm.Time = src
return nil
case string:
newtm, err := internal.ParseTime(src)
if err != nil {
return err
}
tm.Time = newtm
return nil
case []byte:
newtm, err := internal.ParseTime(internal.String(src))
if err != nil {
return err
}
tm.Time = newtm
return nil
default:
return scanError(bunNullTimeType, src)
}
}

1130
vendor/github.com/uptrace/bun/schema/table.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

114
vendor/github.com/uptrace/bun/schema/tables.go generated vendored Normal file
View File

@@ -0,0 +1,114 @@
package schema
import (
"fmt"
"reflect"
"sync"
"github.com/puzpuzpuz/xsync/v3"
)
type Tables struct {
dialect Dialect
mu sync.Mutex
tables *xsync.MapOf[reflect.Type, *Table]
inProgress map[reflect.Type]*Table
}
func NewTables(dialect Dialect) *Tables {
return &Tables{
dialect: dialect,
tables: xsync.NewMapOf[reflect.Type, *Table](),
inProgress: make(map[reflect.Type]*Table),
}
}
func (t *Tables) Register(models ...any) {
for _, model := range models {
_ = t.Get(reflect.TypeOf(model).Elem())
}
}
func (t *Tables) Get(typ reflect.Type) *Table {
typ = indirectType(typ)
if typ.Kind() != reflect.Struct {
panic(fmt.Errorf("got %s, wanted %s", typ.Kind(), reflect.Struct))
}
if v, ok := t.tables.Load(typ); ok {
return v
}
t.mu.Lock()
defer t.mu.Unlock()
if v, ok := t.tables.Load(typ); ok {
return v
}
table := t.InProgress(typ)
table.initRelations()
t.dialect.OnTable(table)
for _, field := range table.FieldMap {
if field.UserSQLType == "" {
field.UserSQLType = field.DiscoveredSQLType
}
if field.CreateTableSQLType == "" {
field.CreateTableSQLType = field.UserSQLType
}
}
t.tables.Store(typ, table)
return table
}
func (t *Tables) InProgress(typ reflect.Type) *Table {
if table, ok := t.inProgress[typ]; ok {
return table
}
table := new(Table)
t.inProgress[typ] = table
table.init(t.dialect, typ)
return table
}
// ByModel gets the table by its Go name.
func (t *Tables) ByModel(name string) *Table {
var found *Table
t.tables.Range(func(typ reflect.Type, table *Table) bool {
if table.TypeName == name {
found = table
return false
}
return true
})
return found
}
// ByName gets the table by its SQL name.
func (t *Tables) ByName(name string) *Table {
var found *Table
t.tables.Range(func(typ reflect.Type, table *Table) bool {
if table.Name == name {
found = table
return false
}
return true
})
return found
}
// All returns all registered tables.
func (t *Tables) All() []*Table {
var found []*Table
t.tables.Range(func(typ reflect.Type, table *Table) bool {
found = append(found, table)
return true
})
return found
}

161
vendor/github.com/uptrace/bun/schema/zerochecker.go generated vendored Normal file
View File

@@ -0,0 +1,161 @@
package schema
import (
"database/sql/driver"
"reflect"
)
var isZeroerType = reflect.TypeFor[isZeroer]()
type isZeroer interface {
IsZero() bool
}
func isZero(v any) bool {
switch v := v.(type) {
case isZeroer:
return v.IsZero()
case string:
return v == ""
case []byte:
return v == nil
case int:
return v == 0
case int64:
return v == 0
case uint:
return v == 0
case uint64:
return v == 0
case float32:
return v == 0
case float64:
return v == 0
case int8:
return v == 0
case int16:
return v == 0
case int32:
return v == 0
case uint8:
return v == 0
case uint16:
return v == 0
case uint32:
return v == 0
default:
rv := reflect.ValueOf(v)
fn := zeroChecker(rv.Type())
return fn(rv)
}
}
type IsZeroerFunc func(reflect.Value) bool
func zeroChecker(typ reflect.Type) IsZeroerFunc {
if typ.Implements(isZeroerType) {
return isZeroInterface
}
kind := typ.Kind()
if kind != reflect.Ptr {
ptr := reflect.PointerTo(typ)
if ptr.Implements(isZeroerType) {
return addrChecker(isZeroInterface)
}
}
switch kind {
case reflect.Array:
if typ.Elem().Kind() == reflect.Uint8 {
return isZeroBytes
}
return isZeroLen
case reflect.String:
return isZeroLen
case reflect.Bool:
return isZeroBool
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return isZeroInt
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return isZeroUint
case reflect.Float32, reflect.Float64:
return isZeroFloat
case reflect.Interface, reflect.Ptr, reflect.Slice, reflect.Map:
return isNil
}
if typ.Implements(driverValuerType) {
return isZeroDriverValue
}
return notZero
}
func addrChecker(fn IsZeroerFunc) IsZeroerFunc {
return func(v reflect.Value) bool {
if !v.CanAddr() {
return false
}
return fn(v.Addr())
}
}
func isZeroInterface(v reflect.Value) bool {
if v.Kind() == reflect.Ptr && v.IsNil() {
return true
}
return v.Interface().(isZeroer).IsZero()
}
func isZeroDriverValue(v reflect.Value) bool {
if v.Kind() == reflect.Ptr {
return v.IsNil()
}
valuer := v.Interface().(driver.Valuer)
value, err := valuer.Value()
if err != nil {
return false
}
return value == nil
}
func isZeroLen(v reflect.Value) bool {
return v.Len() == 0
}
func isNil(v reflect.Value) bool {
return v.IsNil()
}
func isZeroBool(v reflect.Value) bool {
return !v.Bool()
}
func isZeroInt(v reflect.Value) bool {
return v.Int() == 0
}
func isZeroUint(v reflect.Value) bool {
return v.Uint() == 0
}
func isZeroFloat(v reflect.Value) bool {
return v.Float() == 0
}
func isZeroBytes(v reflect.Value) bool {
b := v.Slice(0, v.Len()).Bytes()
for _, c := range b {
if c != 0 {
return false
}
}
return true
}
func notZero(v reflect.Value) bool {
return false
}