mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-13 23:37:28 -06:00
[chore] update bun libraries to v1.2.5 (#3528)
* update bun libraries to v1.2.5 * pin old v1.29.0 of otel
This commit is contained in:
parent
45e1609377
commit
29007b1b88
59 changed files with 4181 additions and 1196 deletions
79
vendor/github.com/uptrace/bun/CHANGELOG.md
generated
vendored
79
vendor/github.com/uptrace/bun/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,70 @@
|
|||
## [1.2.5](https://github.com/uptrace/bun/compare/v1.2.3...v1.2.5) (2024-10-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow Limit() without Order() with MSSQL ([#1009](https://github.com/uptrace/bun/issues/1009)) ([1a46ddc](https://github.com/uptrace/bun/commit/1a46ddc0d3ca0bdc60ca8be5ad1886799d14c8b0))
|
||||
* copy bytes in mapModel.Scan ([#1030](https://github.com/uptrace/bun/issues/1030)) ([#1032](https://github.com/uptrace/bun/issues/1032)) ([39fda4e](https://github.com/uptrace/bun/commit/39fda4e3d341e59e4955f751cb354a939e57c1b1))
|
||||
* fix issue with has-many join and pointer fields ([#950](https://github.com/uptrace/bun/issues/950)) ([#983](https://github.com/uptrace/bun/issues/983)) ([cbc5177](https://github.com/uptrace/bun/commit/cbc517792ba6cdcef1828f3699d3d4dfe3c5e0eb))
|
||||
* restore explicit column: name override ([#984](https://github.com/uptrace/bun/issues/984)) ([169f258](https://github.com/uptrace/bun/commit/169f258a9460cad451f3025d2ef8df1bbd42a003))
|
||||
* return column option back ([#1036](https://github.com/uptrace/bun/issues/1036)) ([a3ccbea](https://github.com/uptrace/bun/commit/a3ccbeab39151d3eed6cb245fe15cfb5d71ba557))
|
||||
* sql.NullString mistaken as custom struct ([#1019](https://github.com/uptrace/bun/issues/1019)) ([87c77b8](https://github.com/uptrace/bun/commit/87c77b8911f2035b0ee8ea96356a2c7600b5b94d))
|
||||
* typos ([#1026](https://github.com/uptrace/bun/issues/1026)) ([760de7d](https://github.com/uptrace/bun/commit/760de7d0fad15dc761475670a4dde056aef9210d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add transaction isolation level support to pgdriver ([#1034](https://github.com/uptrace/bun/issues/1034)) ([3ef44ce](https://github.com/uptrace/bun/commit/3ef44ce1cdd969a21b76d6c803119cf12c375cb0))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* refactor SelectQuery.ScanAndCount to optimize performance when there is no limit and offset ([#1035](https://github.com/uptrace/bun/issues/1035)) ([8638613](https://github.com/uptrace/bun/commit/86386135897485bbada6c50ec9a2743626111433))
|
||||
|
||||
|
||||
|
||||
## [1.2.4](https://github.com/uptrace/bun/compare/v1.2.3...v1.2.4) (2024-10-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow Limit() without Order() with MSSQL ([#1009](https://github.com/uptrace/bun/issues/1009)) ([1a46ddc](https://github.com/uptrace/bun/commit/1a46ddc0d3ca0bdc60ca8be5ad1886799d14c8b0))
|
||||
* copy bytes in mapModel.Scan ([#1030](https://github.com/uptrace/bun/issues/1030)) ([#1032](https://github.com/uptrace/bun/issues/1032)) ([39fda4e](https://github.com/uptrace/bun/commit/39fda4e3d341e59e4955f751cb354a939e57c1b1))
|
||||
* return column option back ([#1036](https://github.com/uptrace/bun/issues/1036)) ([a3ccbea](https://github.com/uptrace/bun/commit/a3ccbeab39151d3eed6cb245fe15cfb5d71ba557))
|
||||
* sql.NullString mistaken as custom struct ([#1019](https://github.com/uptrace/bun/issues/1019)) ([87c77b8](https://github.com/uptrace/bun/commit/87c77b8911f2035b0ee8ea96356a2c7600b5b94d))
|
||||
* typos ([#1026](https://github.com/uptrace/bun/issues/1026)) ([760de7d](https://github.com/uptrace/bun/commit/760de7d0fad15dc761475670a4dde056aef9210d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add transaction isolation level support to pgdriver ([#1034](https://github.com/uptrace/bun/issues/1034)) ([3ef44ce](https://github.com/uptrace/bun/commit/3ef44ce1cdd969a21b76d6c803119cf12c375cb0))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* refactor SelectQuery.ScanAndCount to optimize performance when there is no limit and offset ([#1035](https://github.com/uptrace/bun/issues/1035)) ([8638613](https://github.com/uptrace/bun/commit/86386135897485bbada6c50ec9a2743626111433))
|
||||
|
||||
|
||||
|
||||
## [1.2.3](https://github.com/uptrace/bun/compare/v1.2.2...v1.2.3) (2024-08-31)
|
||||
|
||||
|
||||
|
||||
## [1.2.2](https://github.com/uptrace/bun/compare/v1.2.1...v1.2.2) (2024-08-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* gracefully handle empty hstore in pgdialect ([#1010](https://github.com/uptrace/bun/issues/1010)) ([2f73d8a](https://github.com/uptrace/bun/commit/2f73d8a8e16c8718ebfc956036d9c9a01a0888bc))
|
||||
* number each unit test ([#974](https://github.com/uptrace/bun/issues/974)) ([b005dc2](https://github.com/uptrace/bun/commit/b005dc2a9034715c6f59dcfc8e76aa3b85df38ab))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add ModelTableExpr to TruncateTableQuery ([#969](https://github.com/uptrace/bun/issues/969)) ([7bc330f](https://github.com/uptrace/bun/commit/7bc330f152cf0d9dc30956478e2731ea5816f012))
|
||||
|
||||
|
||||
|
||||
## [1.2.1](https://github.com/uptrace/bun/compare/v1.2.0...v1.2.1) (2024-04-02)
|
||||
|
||||
|
||||
|
|
@ -14,7 +81,7 @@
|
|||
|
||||
### Features
|
||||
|
||||
* Allow overiding of Warn and Deprecated loggers ([#952](https://github.com/uptrace/bun/issues/952)) ([0e9d737](https://github.com/uptrace/bun/commit/0e9d737e4ca2deb86930237ee32a39cf3f7e8157))
|
||||
* Allow overriding of Warn and Deprecated loggers ([#952](https://github.com/uptrace/bun/issues/952)) ([0e9d737](https://github.com/uptrace/bun/commit/0e9d737e4ca2deb86930237ee32a39cf3f7e8157))
|
||||
* enable SNI ([#953](https://github.com/uptrace/bun/issues/953)) ([4071ffb](https://github.com/uptrace/bun/commit/4071ffb5bcb1b233cda239c92504d8139dcf1d2f))
|
||||
* **idb:** add NewMerge method to IDB ([#966](https://github.com/uptrace/bun/issues/966)) ([664e2f1](https://github.com/uptrace/bun/commit/664e2f154f1153d2a80cd062a5074f1692edaee7))
|
||||
|
||||
|
|
@ -100,7 +167,7 @@
|
|||
|
||||
### Bug Fixes
|
||||
|
||||
* add support for inserting values with unicode encoding for mssql dialect ([e98c6c0](https://github.com/uptrace/bun/commit/e98c6c0f033b553bea3bbc783aa56c2eaa17718f))
|
||||
* add support for inserting values with Unicode encoding for mssql dialect ([e98c6c0](https://github.com/uptrace/bun/commit/e98c6c0f033b553bea3bbc783aa56c2eaa17718f))
|
||||
* fix relation tag ([a3eedff](https://github.com/uptrace/bun/commit/a3eedff49700490d4998dcdcdc04f554d8f17166))
|
||||
|
||||
|
||||
|
|
@ -136,7 +203,7 @@
|
|||
|
||||
### Bug Fixes
|
||||
|
||||
* addng dialect override for append-bool ([#695](https://github.com/uptrace/bun/issues/695)) ([338f2f0](https://github.com/uptrace/bun/commit/338f2f04105ad89e64530db86aeb387e2ad4789e))
|
||||
* adding dialect override for append-bool ([#695](https://github.com/uptrace/bun/issues/695)) ([338f2f0](https://github.com/uptrace/bun/commit/338f2f04105ad89e64530db86aeb387e2ad4789e))
|
||||
* don't call hooks twice for whereExists ([9057857](https://github.com/uptrace/bun/commit/90578578e717f248e4b6eb114c5b495fd8d4ed41))
|
||||
* don't lock migrations when running Migrate and Rollback ([69a7354](https://github.com/uptrace/bun/commit/69a7354d987ff2ed5338c9ef5f4ce320724299ab))
|
||||
* **query:** make WhereDeleted compatible with ForceDelete ([299c3fd](https://github.com/uptrace/bun/commit/299c3fd57866aaecd127a8f219c95332898475db)), closes [#673](https://github.com/uptrace/bun/issues/673)
|
||||
|
|
@ -304,7 +371,7 @@ recommended to upgrade to v1.0.24 before upgrading to v1.1.x.
|
|||
|
||||
- append slice values
|
||||
([4a65129](https://github.com/uptrace/bun/commit/4a651294fb0f1e73079553024810c3ead9777311))
|
||||
- check for nils when appeding driver.Value
|
||||
- check for nils when appending driver.Value
|
||||
([7bb1640](https://github.com/uptrace/bun/commit/7bb1640a00fceca1e1075fe6544b9a4842ab2b26))
|
||||
- cleanup soft deletes for mssql
|
||||
([e72e2c5](https://github.com/uptrace/bun/commit/e72e2c5d0a85f3d26c3fa22c7284c2de1dcfda8e))
|
||||
|
|
@ -323,7 +390,7 @@ recommended to upgrade to v1.0.24 before upgrading to v1.1.x.
|
|||
|
||||
### Deprecated
|
||||
|
||||
In the comming v1.1.x release, Bun will stop automatically adding `,pk,autoincrement` options on
|
||||
In the coming v1.1.x release, Bun will stop automatically adding `,pk,autoincrement` options on
|
||||
`ID int64/int32` fields. This version (v1.0.23) only prints a warning when it encounters such
|
||||
fields, but the code will continue working as before.
|
||||
|
||||
|
|
@ -441,7 +508,7 @@ In v1.1.x, such options as `,nopk` and `,allowzero` will not be necessary and wi
|
|||
([693f1e1](https://github.com/uptrace/bun/commit/693f1e135999fc31cf83b99a2530a695b20f4e1b))
|
||||
- add model embedding via embed:prefix\_
|
||||
([9a2cedc](https://github.com/uptrace/bun/commit/9a2cedc8b08fa8585d4bfced338bd0a40d736b1d))
|
||||
- change the default logoutput to stderr
|
||||
- change the default log output to stderr
|
||||
([4bf5773](https://github.com/uptrace/bun/commit/4bf577382f19c64457cbf0d64490401450954654)),
|
||||
closes [#349](https://github.com/uptrace/bun/issues/349)
|
||||
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/Makefile
generated
vendored
2
vendor/github.com/uptrace/bun/Makefile
generated
vendored
|
|
@ -15,7 +15,7 @@ go_mod_tidy:
|
|||
echo "go mod tidy in $${dir}"; \
|
||||
(cd "$${dir}" && \
|
||||
go get -u ./... && \
|
||||
go mod tidy -go=1.21); \
|
||||
go mod tidy); \
|
||||
done
|
||||
|
||||
fmt:
|
||||
|
|
|
|||
3
vendor/github.com/uptrace/bun/README.md
generated
vendored
3
vendor/github.com/uptrace/bun/README.md
generated
vendored
|
|
@ -1,4 +1,4 @@
|
|||
# SQL-first Golang ORM for PostgreSQL, MySQL, MSSQL, and SQLite
|
||||
# SQL-first Golang ORM for PostgreSQL, MySQL, MSSQL, SQLite and Oracle
|
||||
|
||||
[](https://github.com/uptrace/bun/actions)
|
||||
[](https://pkg.go.dev/github.com/uptrace/bun)
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
[MySQL](https://bun.uptrace.dev/guide/drivers.html#mysql) (including MariaDB),
|
||||
[MSSQL](https://bun.uptrace.dev/guide/drivers.html#mssql),
|
||||
[SQLite](https://bun.uptrace.dev/guide/drivers.html#sqlite).
|
||||
[Oracle](https://bun.uptrace.dev/guide/drivers.html#oracle).
|
||||
- [ORM-like](/example/basic/) experience using good old SQL. Bun supports structs, map, scalars, and
|
||||
slices of map/structs/scalars.
|
||||
- [Bulk inserts](https://bun.uptrace.dev/guide/query-insert.html).
|
||||
|
|
|
|||
6
vendor/github.com/uptrace/bun/bun.go
generated
vendored
6
vendor/github.com/uptrace/bun/bun.go
generated
vendored
|
|
@ -22,6 +22,10 @@ type (
|
|||
AfterScanRowHook = schema.AfterScanRowHook
|
||||
)
|
||||
|
||||
func SafeQuery(query string, args ...interface{}) schema.QueryWithArgs {
|
||||
return schema.SafeQuery(query, args)
|
||||
}
|
||||
|
||||
type BeforeSelectHook interface {
|
||||
BeforeSelect(ctx context.Context, query *SelectQuery) error
|
||||
}
|
||||
|
|
@ -70,7 +74,7 @@ type AfterDropTableHook interface {
|
|||
AfterDropTable(ctx context.Context, query *DropTableQuery) error
|
||||
}
|
||||
|
||||
// SetLogger overwriters default Bun logger.
|
||||
// SetLogger overwrites default Bun logger.
|
||||
func SetLogger(logger internal.Logging) {
|
||||
internal.SetLogger(logger)
|
||||
}
|
||||
|
|
|
|||
3
vendor/github.com/uptrace/bun/dialect/dialect.go
generated
vendored
3
vendor/github.com/uptrace/bun/dialect/dialect.go
generated
vendored
|
|
@ -12,6 +12,8 @@ func (n Name) String() string {
|
|||
return "mysql"
|
||||
case MSSQL:
|
||||
return "mssql"
|
||||
case Oracle:
|
||||
return "oracle"
|
||||
default:
|
||||
return "invalid"
|
||||
}
|
||||
|
|
@ -23,4 +25,5 @@ const (
|
|||
SQLite
|
||||
MySQL
|
||||
MSSQL
|
||||
Oracle
|
||||
)
|
||||
|
|
|
|||
313
vendor/github.com/uptrace/bun/dialect/pgdialect/append.go
generated
vendored
313
vendor/github.com/uptrace/bun/dialect/pgdialect/append.go
generated
vendored
|
|
@ -2,12 +2,9 @@ package pgdialect
|
|||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/uptrace/bun/dialect"
|
||||
"github.com/uptrace/bun/schema"
|
||||
|
|
@ -32,316 +29,10 @@ var (
|
|||
sliceTimeType = reflect.TypeOf([]time.Time(nil))
|
||||
)
|
||||
|
||||
func arrayAppend(fmter schema.Formatter, b []byte, v interface{}) []byte {
|
||||
switch v := v.(type) {
|
||||
case int64:
|
||||
return strconv.AppendInt(b, v, 10)
|
||||
case float64:
|
||||
return dialect.AppendFloat64(b, v)
|
||||
case bool:
|
||||
return dialect.AppendBool(b, v)
|
||||
case []byte:
|
||||
return arrayAppendBytes(b, v)
|
||||
case string:
|
||||
return arrayAppendString(b, v)
|
||||
case time.Time:
|
||||
return fmter.Dialect().AppendTime(b, v)
|
||||
default:
|
||||
err := fmt.Errorf("pgdialect: can't append %T", v)
|
||||
return dialect.AppendError(b, err)
|
||||
}
|
||||
func appendTime(buf []byte, tm time.Time) []byte {
|
||||
return tm.UTC().AppendFormat(buf, "2006-01-02 15:04:05.999999-07:00")
|
||||
}
|
||||
|
||||
func arrayAppendStringValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
return arrayAppendString(b, v.String())
|
||||
}
|
||||
|
||||
func arrayAppendBytesValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
return arrayAppendBytes(b, v.Bytes())
|
||||
}
|
||||
|
||||
func arrayAppendDriverValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
iface, err := v.Interface().(driver.Valuer).Value()
|
||||
if err != nil {
|
||||
return dialect.AppendError(b, err)
|
||||
}
|
||||
return arrayAppend(fmter, b, iface)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func (d *Dialect) arrayAppender(typ reflect.Type) schema.AppenderFunc {
|
||||
kind := typ.Kind()
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
if fn := d.arrayAppender(typ.Elem()); fn != nil {
|
||||
return schema.PtrAppender(fn)
|
||||
}
|
||||
case reflect.Slice, reflect.Array:
|
||||
// ok:
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
elemType := typ.Elem()
|
||||
|
||||
if kind == reflect.Slice {
|
||||
switch elemType {
|
||||
case stringType:
|
||||
return appendStringSliceValue
|
||||
case intType:
|
||||
return appendIntSliceValue
|
||||
case int64Type:
|
||||
return appendInt64SliceValue
|
||||
case float64Type:
|
||||
return appendFloat64SliceValue
|
||||
case timeType:
|
||||
return appendTimeSliceValue
|
||||
}
|
||||
}
|
||||
|
||||
appendElem := d.arrayElemAppender(elemType)
|
||||
if appendElem == nil {
|
||||
panic(fmt.Errorf("pgdialect: %s is not supported", typ))
|
||||
}
|
||||
|
||||
return func(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
kind := v.Kind()
|
||||
switch kind {
|
||||
case reflect.Ptr, reflect.Slice:
|
||||
if v.IsNil() {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
}
|
||||
|
||||
if kind == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
ln := v.Len()
|
||||
for i := 0; i < ln; i++ {
|
||||
elem := v.Index(i)
|
||||
b = appendElem(fmter, b, elem)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if v.Len() > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dialect) arrayElemAppender(typ reflect.Type) schema.AppenderFunc {
|
||||
if typ.Implements(driverValuerType) {
|
||||
return arrayAppendDriverValue
|
||||
}
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
return arrayAppendStringValue
|
||||
case reflect.Slice:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
return arrayAppendBytesValue
|
||||
}
|
||||
}
|
||||
return schema.Appender(d, typ)
|
||||
}
|
||||
|
||||
func appendStringSliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ss := v.Convert(sliceStringType).Interface().([]string)
|
||||
return appendStringSlice(b, ss)
|
||||
}
|
||||
|
||||
func appendStringSlice(b []byte, ss []string) []byte {
|
||||
if ss == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, s := range ss {
|
||||
b = arrayAppendString(b, s)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendIntSliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ints := v.Convert(sliceIntType).Interface().([]int)
|
||||
return appendIntSlice(b, ints)
|
||||
}
|
||||
|
||||
func appendIntSlice(b []byte, ints []int) []byte {
|
||||
if ints == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, n := range ints {
|
||||
b = strconv.AppendInt(b, int64(n), 10)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ints) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendInt64SliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ints := v.Convert(sliceInt64Type).Interface().([]int64)
|
||||
return appendInt64Slice(b, ints)
|
||||
}
|
||||
|
||||
func appendInt64Slice(b []byte, ints []int64) []byte {
|
||||
if ints == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, n := range ints {
|
||||
b = strconv.AppendInt(b, n, 10)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ints) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendFloat64SliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
floats := v.Convert(sliceFloat64Type).Interface().([]float64)
|
||||
return appendFloat64Slice(b, floats)
|
||||
}
|
||||
|
||||
func appendFloat64Slice(b []byte, floats []float64) []byte {
|
||||
if floats == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, n := range floats {
|
||||
b = dialect.AppendFloat64(b, n)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(floats) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func arrayAppendBytes(b []byte, 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 arrayAppendString(b []byte, s string) []byte {
|
||||
b = append(b, '"')
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case 0:
|
||||
// ignore
|
||||
case '\'':
|
||||
b = append(b, "''"...)
|
||||
case '"':
|
||||
b = append(b, '\\', '"')
|
||||
case '\\':
|
||||
b = append(b, '\\', '\\')
|
||||
default:
|
||||
if r < utf8.RuneSelf {
|
||||
b = append(b, byte(r))
|
||||
break
|
||||
}
|
||||
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 appendTimeSliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ts := v.Convert(sliceTimeType).Interface().([]time.Time)
|
||||
return appendTimeSlice(fmter, b, ts)
|
||||
}
|
||||
|
||||
func appendTimeSlice(fmter schema.Formatter, b []byte, ts []time.Time) []byte {
|
||||
if ts == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
b = append(b, '\'')
|
||||
b = append(b, '{')
|
||||
for _, t := range ts {
|
||||
b = append(b, '"')
|
||||
b = t.UTC().AppendFormat(b, "2006-01-02 15:04:05.999999-07:00")
|
||||
b = append(b, '"')
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ts) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
b = append(b, '\'')
|
||||
return b
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
var mapStringStringType = reflect.TypeOf(map[string]string(nil))
|
||||
|
||||
func (d *Dialect) hstoreAppender(typ reflect.Type) schema.AppenderFunc {
|
||||
|
|
|
|||
582
vendor/github.com/uptrace/bun/dialect/pgdialect/array.go
generated
vendored
582
vendor/github.com/uptrace/bun/dialect/pgdialect/array.go
generated
vendored
|
|
@ -2,9 +2,16 @@ package pgdialect
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/uptrace/bun/dialect"
|
||||
"github.com/uptrace/bun/internal"
|
||||
"github.com/uptrace/bun/schema"
|
||||
)
|
||||
|
||||
|
|
@ -20,7 +27,7 @@ type ArrayValue struct {
|
|||
//
|
||||
// For struct fields you can use array tag:
|
||||
//
|
||||
// Emails []string `bun:",array"`
|
||||
// Emails []string `bun:",array"`
|
||||
func Array(vi interface{}) *ArrayValue {
|
||||
v := reflect.ValueOf(vi)
|
||||
if !v.IsValid() {
|
||||
|
|
@ -63,3 +70,576 @@ func (a *ArrayValue) Value() interface{} {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func (d *Dialect) arrayAppender(typ reflect.Type) schema.AppenderFunc {
|
||||
kind := typ.Kind()
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
if fn := d.arrayAppender(typ.Elem()); fn != nil {
|
||||
return schema.PtrAppender(fn)
|
||||
}
|
||||
case reflect.Slice, reflect.Array:
|
||||
// continue below
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
elemType := typ.Elem()
|
||||
|
||||
if kind == reflect.Slice {
|
||||
switch elemType {
|
||||
case stringType:
|
||||
return appendStringSliceValue
|
||||
case intType:
|
||||
return appendIntSliceValue
|
||||
case int64Type:
|
||||
return appendInt64SliceValue
|
||||
case float64Type:
|
||||
return appendFloat64SliceValue
|
||||
case timeType:
|
||||
return appendTimeSliceValue
|
||||
}
|
||||
}
|
||||
|
||||
appendElem := d.arrayElemAppender(elemType)
|
||||
if appendElem == nil {
|
||||
panic(fmt.Errorf("pgdialect: %s is not supported", typ))
|
||||
}
|
||||
|
||||
return func(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
kind := v.Kind()
|
||||
switch kind {
|
||||
case reflect.Ptr, reflect.Slice:
|
||||
if v.IsNil() {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
}
|
||||
|
||||
if kind == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
b = append(b, "'{"...)
|
||||
|
||||
ln := v.Len()
|
||||
for i := 0; i < ln; i++ {
|
||||
elem := v.Index(i)
|
||||
if i > 0 {
|
||||
b = append(b, ',')
|
||||
}
|
||||
b = appendElem(fmter, b, elem)
|
||||
}
|
||||
|
||||
b = append(b, "}'"...)
|
||||
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dialect) arrayElemAppender(typ reflect.Type) schema.AppenderFunc {
|
||||
if typ.Implements(driverValuerType) {
|
||||
return arrayAppendDriverValue
|
||||
}
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
return arrayAppendStringValue
|
||||
case reflect.Slice:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
return arrayAppendBytesValue
|
||||
}
|
||||
}
|
||||
return schema.Appender(d, typ)
|
||||
}
|
||||
|
||||
func arrayAppend(fmter schema.Formatter, b []byte, v interface{}) []byte {
|
||||
switch v := v.(type) {
|
||||
case int64:
|
||||
return strconv.AppendInt(b, v, 10)
|
||||
case float64:
|
||||
return dialect.AppendFloat64(b, v)
|
||||
case bool:
|
||||
return dialect.AppendBool(b, v)
|
||||
case []byte:
|
||||
return arrayAppendBytes(b, v)
|
||||
case string:
|
||||
return arrayAppendString(b, v)
|
||||
case time.Time:
|
||||
return fmter.Dialect().AppendTime(b, v)
|
||||
default:
|
||||
err := fmt.Errorf("pgdialect: can't append %T", v)
|
||||
return dialect.AppendError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
func arrayAppendStringValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
return arrayAppendString(b, v.String())
|
||||
}
|
||||
|
||||
func arrayAppendBytesValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
return arrayAppendBytes(b, v.Bytes())
|
||||
}
|
||||
|
||||
func arrayAppendDriverValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
iface, err := v.Interface().(driver.Valuer).Value()
|
||||
if err != nil {
|
||||
return dialect.AppendError(b, err)
|
||||
}
|
||||
return arrayAppend(fmter, b, iface)
|
||||
}
|
||||
|
||||
func appendStringSliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ss := v.Convert(sliceStringType).Interface().([]string)
|
||||
return appendStringSlice(b, ss)
|
||||
}
|
||||
|
||||
func appendStringSlice(b []byte, ss []string) []byte {
|
||||
if ss == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, s := range ss {
|
||||
b = arrayAppendString(b, s)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendIntSliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ints := v.Convert(sliceIntType).Interface().([]int)
|
||||
return appendIntSlice(b, ints)
|
||||
}
|
||||
|
||||
func appendIntSlice(b []byte, ints []int) []byte {
|
||||
if ints == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, n := range ints {
|
||||
b = strconv.AppendInt(b, int64(n), 10)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ints) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendInt64SliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ints := v.Convert(sliceInt64Type).Interface().([]int64)
|
||||
return appendInt64Slice(b, ints)
|
||||
}
|
||||
|
||||
func appendInt64Slice(b []byte, ints []int64) []byte {
|
||||
if ints == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, n := range ints {
|
||||
b = strconv.AppendInt(b, n, 10)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ints) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendFloat64SliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
floats := v.Convert(sliceFloat64Type).Interface().([]float64)
|
||||
return appendFloat64Slice(b, floats)
|
||||
}
|
||||
|
||||
func appendFloat64Slice(b []byte, floats []float64) []byte {
|
||||
if floats == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
b = append(b, '{')
|
||||
for _, n := range floats {
|
||||
b = dialect.AppendFloat64(b, n)
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(floats) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
|
||||
b = append(b, '\'')
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func appendTimeSliceValue(fmter schema.Formatter, b []byte, v reflect.Value) []byte {
|
||||
ts := v.Convert(sliceTimeType).Interface().([]time.Time)
|
||||
return appendTimeSlice(fmter, b, ts)
|
||||
}
|
||||
|
||||
func appendTimeSlice(fmter schema.Formatter, b []byte, ts []time.Time) []byte {
|
||||
if ts == nil {
|
||||
return dialect.AppendNull(b)
|
||||
}
|
||||
b = append(b, '\'')
|
||||
b = append(b, '{')
|
||||
for _, t := range ts {
|
||||
b = append(b, '"')
|
||||
b = appendTime(b, t)
|
||||
b = append(b, '"')
|
||||
b = append(b, ',')
|
||||
}
|
||||
if len(ts) > 0 {
|
||||
b[len(b)-1] = '}' // Replace trailing comma.
|
||||
} else {
|
||||
b = append(b, '}')
|
||||
}
|
||||
b = append(b, '\'')
|
||||
return b
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func arrayScanner(typ reflect.Type) schema.ScannerFunc {
|
||||
kind := typ.Kind()
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
if fn := arrayScanner(typ.Elem()); fn != nil {
|
||||
return schema.PtrScanner(fn)
|
||||
}
|
||||
case reflect.Slice, reflect.Array:
|
||||
// ok:
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
elemType := typ.Elem()
|
||||
|
||||
if kind == reflect.Slice {
|
||||
switch elemType {
|
||||
case stringType:
|
||||
return scanStringSliceValue
|
||||
case intType:
|
||||
return scanIntSliceValue
|
||||
case int64Type:
|
||||
return scanInt64SliceValue
|
||||
case float64Type:
|
||||
return scanFloat64SliceValue
|
||||
}
|
||||
}
|
||||
|
||||
scanElem := schema.Scanner(elemType)
|
||||
return func(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
kind := dest.Kind()
|
||||
|
||||
if src == nil {
|
||||
if kind != reflect.Slice || !dest.IsNil() {
|
||||
dest.Set(reflect.Zero(dest.Type()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if kind == reflect.Slice {
|
||||
if dest.IsNil() {
|
||||
dest.Set(reflect.MakeSlice(dest.Type(), 0, 0))
|
||||
} else if dest.Len() > 0 {
|
||||
dest.Set(dest.Slice(0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := newArrayParser(b)
|
||||
nextValue := internal.MakeSliceNextElemFunc(dest)
|
||||
for p.Next() {
|
||||
elem := p.Elem()
|
||||
elemValue := nextValue()
|
||||
if err := scanElem(elemValue, elem); err != nil {
|
||||
return fmt.Errorf("scanElem failed: %w", err)
|
||||
}
|
||||
}
|
||||
return p.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func scanStringSliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := decodeStringSlice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeStringSlice(src interface{}) ([]string, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]string, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for p.Next() {
|
||||
elem := p.Elem()
|
||||
slice = append(slice, string(elem))
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func scanIntSliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := decodeIntSlice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeIntSlice(src interface{}) ([]int, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]int, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for p.Next() {
|
||||
elem := p.Elem()
|
||||
|
||||
if elem == nil {
|
||||
slice = append(slice, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := strconv.Atoi(bytesToString(elem))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice = append(slice, n)
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func scanInt64SliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := decodeInt64Slice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeInt64Slice(src interface{}) ([]int64, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]int64, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for p.Next() {
|
||||
elem := p.Elem()
|
||||
|
||||
if elem == nil {
|
||||
slice = append(slice, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := strconv.ParseInt(bytesToString(elem), 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice = append(slice, n)
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func scanFloat64SliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := scanFloat64Slice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func scanFloat64Slice(src interface{}) ([]float64, error) {
|
||||
if src == -1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]float64, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for p.Next() {
|
||||
elem := p.Elem()
|
||||
|
||||
if elem == nil {
|
||||
slice = append(slice, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := strconv.ParseFloat(bytesToString(elem), 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice = append(slice, n)
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func toBytes(src interface{}) ([]byte, error) {
|
||||
switch src := src.(type) {
|
||||
case string:
|
||||
return stringToBytes(src), nil
|
||||
case []byte:
|
||||
return src, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("bun: got %T, wanted []byte or string", src)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func arrayAppendBytes(b []byte, 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 arrayAppendString(b []byte, s string) []byte {
|
||||
b = append(b, '"')
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case 0:
|
||||
// ignore
|
||||
case '\'':
|
||||
b = append(b, "''"...)
|
||||
case '"':
|
||||
b = append(b, '\\', '"')
|
||||
case '\\':
|
||||
b = append(b, '\\', '\\')
|
||||
default:
|
||||
if r < utf8.RuneSelf {
|
||||
b = append(b, byte(r))
|
||||
break
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
|||
158
vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go
generated
vendored
158
vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go
generated
vendored
|
|
@ -2,132 +2,92 @@ package pgdialect
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type arrayParser struct {
|
||||
*streamParser
|
||||
err error
|
||||
p pgparser
|
||||
|
||||
elem []byte
|
||||
err error
|
||||
}
|
||||
|
||||
func newArrayParser(b []byte) *arrayParser {
|
||||
p := &arrayParser{
|
||||
streamParser: newStreamParser(b, 1),
|
||||
}
|
||||
p := new(arrayParser)
|
||||
|
||||
if len(b) < 2 || b[0] != '{' || b[len(b)-1] != '}' {
|
||||
p.err = fmt.Errorf("bun: can't parse array: %q", b)
|
||||
p.err = fmt.Errorf("pgdialect: can't parse array: %q", b)
|
||||
return p
|
||||
}
|
||||
|
||||
p.p.Reset(b[1 : len(b)-1])
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *arrayParser) NextElem() ([]byte, error) {
|
||||
func (p *arrayParser) Next() bool {
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
return false
|
||||
}
|
||||
p.err = p.readNext()
|
||||
return p.err == nil
|
||||
}
|
||||
|
||||
func (p *arrayParser) Err() error {
|
||||
if p.err != io.EOF {
|
||||
return p.err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *arrayParser) Elem() []byte {
|
||||
return p.elem
|
||||
}
|
||||
|
||||
func (p *arrayParser) readNext() error {
|
||||
ch := p.p.Read()
|
||||
if ch == 0 {
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
c, err := p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch c {
|
||||
switch ch {
|
||||
case '}':
|
||||
return nil, io.EOF
|
||||
return io.EOF
|
||||
case '"':
|
||||
b, err := p.readSubstring()
|
||||
b, err := p.p.ReadSubstring(ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if p.peek() == ',' {
|
||||
p.skipNext()
|
||||
if p.p.Peek() == ',' {
|
||||
p.p.Advance()
|
||||
}
|
||||
|
||||
return b, nil
|
||||
p.elem = b
|
||||
return nil
|
||||
case '[', '(':
|
||||
rng, err := p.p.ReadRange(ch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.p.Peek() == ',' {
|
||||
p.p.Advance()
|
||||
}
|
||||
|
||||
p.elem = rng
|
||||
return nil
|
||||
default:
|
||||
b := p.readSimple()
|
||||
if bytes.Equal(b, []byte("NULL")) {
|
||||
b = nil
|
||||
lit := p.p.ReadLiteral(ch)
|
||||
if bytes.Equal(lit, []byte("NULL")) {
|
||||
lit = nil
|
||||
}
|
||||
|
||||
if p.peek() == ',' {
|
||||
p.skipNext()
|
||||
if p.p.Peek() == ',' {
|
||||
p.p.Advance()
|
||||
}
|
||||
|
||||
return b, nil
|
||||
p.elem = lit
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *arrayParser) readSimple() []byte {
|
||||
p.unreadByte()
|
||||
|
||||
if i := bytes.IndexByte(p.b[p.i:], ','); i >= 0 {
|
||||
b := p.b[p.i : p.i+i]
|
||||
p.i += i
|
||||
return b
|
||||
}
|
||||
|
||||
b := p.b[p.i : len(p.b)-1]
|
||||
p.i = len(p.b) - 1
|
||||
return b
|
||||
}
|
||||
|
||||
func (p *arrayParser) readSubstring() ([]byte, error) {
|
||||
c, err := p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.buf = p.buf[:0]
|
||||
for {
|
||||
if c == '"' {
|
||||
break
|
||||
}
|
||||
|
||||
next, err := p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c == '\\' {
|
||||
switch next {
|
||||
case '\\', '"':
|
||||
p.buf = append(p.buf, next)
|
||||
|
||||
c, err = p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
p.buf = append(p.buf, '\\')
|
||||
c = next
|
||||
}
|
||||
continue
|
||||
}
|
||||
if c == '\'' && next == '\'' {
|
||||
p.buf = append(p.buf, next)
|
||||
c, err = p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
p.buf = append(p.buf, c)
|
||||
c = next
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(p.buf, []byte("\\x")) && len(p.buf)%2 == 0 {
|
||||
data := p.buf[2:]
|
||||
buf := make([]byte, hex.DecodedLen(len(data)))
|
||||
n, err := hex.Decode(buf, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf[:n], nil
|
||||
}
|
||||
|
||||
return p.buf, nil
|
||||
}
|
||||
|
|
|
|||
301
vendor/github.com/uptrace/bun/dialect/pgdialect/array_scan.go
generated
vendored
301
vendor/github.com/uptrace/bun/dialect/pgdialect/array_scan.go
generated
vendored
|
|
@ -1,302 +1 @@
|
|||
package pgdialect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/uptrace/bun/internal"
|
||||
"github.com/uptrace/bun/schema"
|
||||
)
|
||||
|
||||
func arrayScanner(typ reflect.Type) schema.ScannerFunc {
|
||||
kind := typ.Kind()
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
if fn := arrayScanner(typ.Elem()); fn != nil {
|
||||
return schema.PtrScanner(fn)
|
||||
}
|
||||
case reflect.Slice, reflect.Array:
|
||||
// ok:
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
elemType := typ.Elem()
|
||||
|
||||
if kind == reflect.Slice {
|
||||
switch elemType {
|
||||
case stringType:
|
||||
return scanStringSliceValue
|
||||
case intType:
|
||||
return scanIntSliceValue
|
||||
case int64Type:
|
||||
return scanInt64SliceValue
|
||||
case float64Type:
|
||||
return scanFloat64SliceValue
|
||||
}
|
||||
}
|
||||
|
||||
scanElem := schema.Scanner(elemType)
|
||||
return func(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
kind := dest.Kind()
|
||||
|
||||
if src == nil {
|
||||
if kind != reflect.Slice || !dest.IsNil() {
|
||||
dest.Set(reflect.Zero(dest.Type()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if kind == reflect.Slice {
|
||||
if dest.IsNil() {
|
||||
dest.Set(reflect.MakeSlice(dest.Type(), 0, 0))
|
||||
} else if dest.Len() > 0 {
|
||||
dest.Set(dest.Slice(0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := newArrayParser(b)
|
||||
nextValue := internal.MakeSliceNextElemFunc(dest)
|
||||
for {
|
||||
elem, err := p.NextElem()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
elemValue := nextValue()
|
||||
if err := scanElem(elemValue, elem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func scanStringSliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := decodeStringSlice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeStringSlice(src interface{}) ([]string, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]string, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for {
|
||||
elem, err := p.NextElem()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
slice = append(slice, string(elem))
|
||||
}
|
||||
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func scanIntSliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := decodeIntSlice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeIntSlice(src interface{}) ([]int, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]int, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for {
|
||||
elem, err := p.NextElem()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if elem == nil {
|
||||
slice = append(slice, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := strconv.Atoi(bytesToString(elem))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice = append(slice, n)
|
||||
}
|
||||
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func scanInt64SliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := decodeInt64Slice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeInt64Slice(src interface{}) ([]int64, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]int64, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for {
|
||||
elem, err := p.NextElem()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if elem == nil {
|
||||
slice = append(slice, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := strconv.ParseInt(bytesToString(elem), 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice = append(slice, n)
|
||||
}
|
||||
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func scanFloat64SliceValue(dest reflect.Value, src interface{}) error {
|
||||
dest = reflect.Indirect(dest)
|
||||
if !dest.CanSet() {
|
||||
return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
|
||||
}
|
||||
|
||||
slice, err := scanFloat64Slice(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func scanFloat64Slice(src interface{}) ([]float64, error) {
|
||||
if src == -1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := toBytes(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice := make([]float64, 0)
|
||||
|
||||
p := newArrayParser(b)
|
||||
for {
|
||||
elem, err := p.NextElem()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if elem == nil {
|
||||
slice = append(slice, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := strconv.ParseFloat(bytesToString(elem), 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slice = append(slice, n)
|
||||
}
|
||||
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
func toBytes(src interface{}) ([]byte, error) {
|
||||
switch src := src.(type) {
|
||||
case string:
|
||||
return stringToBytes(src), nil
|
||||
case []byte:
|
||||
return src, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("bun: got %T, wanted []byte or string", src)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go
generated
vendored
10
vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go
generated
vendored
|
|
@ -89,9 +89,17 @@ func (d *Dialect) onField(field *schema.Field) {
|
|||
if field.Tag.HasOption("array") || strings.HasSuffix(field.UserSQLType, "[]") {
|
||||
field.Append = d.arrayAppender(field.StructField.Type)
|
||||
field.Scan = arrayScanner(field.StructField.Type)
|
||||
return
|
||||
}
|
||||
|
||||
if field.DiscoveredSQLType == sqltype.HSTORE {
|
||||
if field.Tag.HasOption("multirange") {
|
||||
field.Append = d.arrayAppender(field.StructField.Type)
|
||||
field.Scan = arrayScanner(field.StructField.Type)
|
||||
return
|
||||
}
|
||||
|
||||
switch field.DiscoveredSQLType {
|
||||
case sqltype.HSTORE:
|
||||
field.Append = d.hstoreAppender(field.StructField.Type)
|
||||
field.Scan = hstoreScanner(field.StructField.Type)
|
||||
}
|
||||
|
|
|
|||
172
vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go
generated
vendored
172
vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go
generated
vendored
|
|
@ -3,140 +3,98 @@ package pgdialect
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type hstoreParser struct {
|
||||
*streamParser
|
||||
err error
|
||||
p pgparser
|
||||
|
||||
key string
|
||||
value string
|
||||
err error
|
||||
}
|
||||
|
||||
func newHStoreParser(b []byte) *hstoreParser {
|
||||
p := &hstoreParser{
|
||||
streamParser: newStreamParser(b, 0),
|
||||
}
|
||||
if len(b) < 6 || b[0] != '"' {
|
||||
p.err = fmt.Errorf("bun: can't parse hstore: %q", b)
|
||||
p := new(hstoreParser)
|
||||
if len(b) != 0 && (len(b) < 6 || b[0] != '"') {
|
||||
p.err = fmt.Errorf("pgdialect: can't parse hstore: %q", b)
|
||||
return p
|
||||
}
|
||||
p.p.Reset(b)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *hstoreParser) NextKey() (string, error) {
|
||||
func (p *hstoreParser) Next() bool {
|
||||
if p.err != nil {
|
||||
return "", p.err
|
||||
return false
|
||||
}
|
||||
|
||||
err := p.skipByte('"')
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
key, err := p.readSubstring()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
const separator = "=>"
|
||||
|
||||
for i := range separator {
|
||||
err = p.skipByte(separator[i])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return string(key), nil
|
||||
p.err = p.readNext()
|
||||
return p.err == nil
|
||||
}
|
||||
|
||||
func (p *hstoreParser) NextValue() (string, error) {
|
||||
if p.err != nil {
|
||||
return "", p.err
|
||||
func (p *hstoreParser) Err() error {
|
||||
if p.err != io.EOF {
|
||||
return p.err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *hstoreParser) Key() string {
|
||||
return p.key
|
||||
}
|
||||
|
||||
func (p *hstoreParser) Value() string {
|
||||
return p.value
|
||||
}
|
||||
|
||||
func (p *hstoreParser) readNext() error {
|
||||
if !p.p.Valid() {
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
c, err := p.readByte()
|
||||
if err := p.p.Skip('"'); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := p.p.ReadUnescapedSubstring('"')
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
p.key = string(key)
|
||||
|
||||
if err := p.p.SkipPrefix([]byte("=>")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c {
|
||||
ch, err := p.p.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch ch {
|
||||
case '"':
|
||||
value, err := p.readSubstring()
|
||||
value, err := p.p.ReadUnescapedSubstring(ch)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
if p.peek() == ',' {
|
||||
p.skipNext()
|
||||
}
|
||||
|
||||
if p.peek() == ' ' {
|
||||
p.skipNext()
|
||||
}
|
||||
|
||||
return string(value), nil
|
||||
p.skipComma()
|
||||
p.value = string(value)
|
||||
return nil
|
||||
default:
|
||||
value := p.readSimple()
|
||||
value := p.p.ReadLiteral(ch)
|
||||
if bytes.Equal(value, []byte("NULL")) {
|
||||
value = nil
|
||||
p.value = ""
|
||||
}
|
||||
|
||||
if p.peek() == ',' {
|
||||
p.skipNext()
|
||||
}
|
||||
|
||||
return string(value), nil
|
||||
p.skipComma()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *hstoreParser) readSimple() []byte {
|
||||
p.unreadByte()
|
||||
|
||||
if i := bytes.IndexByte(p.b[p.i:], ','); i >= 0 {
|
||||
b := p.b[p.i : p.i+i]
|
||||
p.i += i
|
||||
return b
|
||||
func (p *hstoreParser) skipComma() {
|
||||
if p.p.Peek() == ',' {
|
||||
p.p.Advance()
|
||||
}
|
||||
if p.p.Peek() == ' ' {
|
||||
p.p.Advance()
|
||||
}
|
||||
|
||||
b := p.b[p.i:len(p.b)]
|
||||
p.i = len(p.b)
|
||||
return b
|
||||
}
|
||||
|
||||
func (p *hstoreParser) readSubstring() ([]byte, error) {
|
||||
c, err := p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.buf = p.buf[:0]
|
||||
for {
|
||||
if c == '"' {
|
||||
break
|
||||
}
|
||||
|
||||
next, err := p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c == '\\' {
|
||||
switch next {
|
||||
case '\\', '"':
|
||||
p.buf = append(p.buf, next)
|
||||
|
||||
c, err = p.readByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
p.buf = append(p.buf, '\\')
|
||||
c = next
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
p.buf = append(p.buf, c)
|
||||
c = next
|
||||
}
|
||||
|
||||
return p.buf, nil
|
||||
}
|
||||
|
|
|
|||
25
vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_scan.go
generated
vendored
25
vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_scan.go
generated
vendored
|
|
@ -2,7 +2,6 @@ package pgdialect
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/uptrace/bun/schema"
|
||||
|
|
@ -58,25 +57,11 @@ func decodeMapStringString(src interface{}) (map[string]string, error) {
|
|||
m := make(map[string]string)
|
||||
|
||||
p := newHStoreParser(b)
|
||||
for {
|
||||
key, err := p.NextKey()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value, err := p.NextValue()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m[key] = value
|
||||
for p.Next() {
|
||||
m[p.Key()] = p.Value()
|
||||
}
|
||||
if err := p.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
|
|
|||
240
vendor/github.com/uptrace/bun/dialect/pgdialect/range.go
generated
vendored
Normal file
240
vendor/github.com/uptrace/bun/dialect/pgdialect/range.go
generated
vendored
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
package pgdialect
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun/internal"
|
||||
"github.com/uptrace/bun/internal/parser"
|
||||
"github.com/uptrace/bun/schema"
|
||||
)
|
||||
|
||||
type MultiRange[T any] []Range[T]
|
||||
|
||||
type Range[T any] struct {
|
||||
Lower, Upper T
|
||||
LowerBound, UpperBound RangeBound
|
||||
}
|
||||
|
||||
type RangeBound byte
|
||||
|
||||
const (
|
||||
RangeBoundInclusiveLeft RangeBound = '['
|
||||
RangeBoundInclusiveRight RangeBound = ']'
|
||||
RangeBoundExclusiveLeft RangeBound = '('
|
||||
RangeBoundExclusiveRight RangeBound = ')'
|
||||
)
|
||||
|
||||
func NewRange[T any](lower, upper T) Range[T] {
|
||||
return Range[T]{
|
||||
Lower: lower,
|
||||
Upper: upper,
|
||||
LowerBound: RangeBoundInclusiveLeft,
|
||||
UpperBound: RangeBoundExclusiveRight,
|
||||
}
|
||||
}
|
||||
|
||||
var _ sql.Scanner = (*Range[any])(nil)
|
||||
|
||||
func (r *Range[T]) Scan(anySrc any) (err error) {
|
||||
src := anySrc.([]byte)
|
||||
|
||||
if len(src) == 0 {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
r.LowerBound = RangeBound(src[0])
|
||||
src = src[1:]
|
||||
|
||||
src, err = scanElem(&r.Lower, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(src) == 0 {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if ch := src[0]; ch != ',' {
|
||||
return fmt.Errorf("got %q, wanted %q", ch, ',')
|
||||
}
|
||||
src = src[1:]
|
||||
|
||||
src, err = scanElem(&r.Upper, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(src) == 0 {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
r.UpperBound = RangeBound(src[0])
|
||||
src = src[1:]
|
||||
|
||||
if len(src) > 0 {
|
||||
return fmt.Errorf("unread data: %q", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ schema.QueryAppender = (*Range[any])(nil)
|
||||
|
||||
func (r *Range[T]) AppendQuery(fmt schema.Formatter, buf []byte) ([]byte, error) {
|
||||
buf = append(buf, byte(r.LowerBound))
|
||||
buf = appendElem(buf, r.Lower)
|
||||
buf = append(buf, ',')
|
||||
buf = appendElem(buf, r.Upper)
|
||||
buf = append(buf, byte(r.UpperBound))
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func appendElem(buf []byte, val any) []byte {
|
||||
switch val := val.(type) {
|
||||
case time.Time:
|
||||
buf = append(buf, '"')
|
||||
buf = appendTime(buf, val)
|
||||
buf = append(buf, '"')
|
||||
return buf
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported range type: %T", val))
|
||||
}
|
||||
}
|
||||
|
||||
func scanElem(ptr any, src []byte) ([]byte, error) {
|
||||
switch ptr := ptr.(type) {
|
||||
case *time.Time:
|
||||
src, str, err := readStringLiteral(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tm, err := internal.ParseTime(internal.String(str))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*ptr = tm
|
||||
|
||||
return src, nil
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported range type: %T", ptr))
|
||||
}
|
||||
}
|
||||
|
||||
func readStringLiteral(src []byte) ([]byte, []byte, error) {
|
||||
p := newParser(src)
|
||||
|
||||
if err := p.Skip('"'); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
str, err := p.ReadSubstring('"')
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
src = p.Remaining()
|
||||
return src, str, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type pgparser struct {
|
||||
parser.Parser
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func newParser(b []byte) *pgparser {
|
||||
p := new(pgparser)
|
||||
p.Reset(b)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *pgparser) ReadLiteral(ch byte) []byte {
|
||||
p.Unread()
|
||||
lit, _ := p.ReadSep(',')
|
||||
return lit
|
||||
}
|
||||
|
||||
func (p *pgparser) ReadUnescapedSubstring(ch byte) ([]byte, error) {
|
||||
return p.readSubstring(ch, false)
|
||||
}
|
||||
|
||||
func (p *pgparser) ReadSubstring(ch byte) ([]byte, error) {
|
||||
return p.readSubstring(ch, true)
|
||||
}
|
||||
|
||||
func (p *pgparser) readSubstring(ch byte, escaped bool) ([]byte, error) {
|
||||
ch, err := p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.buf = p.buf[:0]
|
||||
for {
|
||||
if ch == '"' {
|
||||
break
|
||||
}
|
||||
|
||||
next, err := p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ch == '\\' {
|
||||
switch next {
|
||||
case '\\', '"':
|
||||
p.buf = append(p.buf, next)
|
||||
|
||||
ch, err = p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
p.buf = append(p.buf, '\\')
|
||||
ch = next
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if escaped && ch == '\'' && next == '\'' {
|
||||
p.buf = append(p.buf, next)
|
||||
ch, err = p.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
p.buf = append(p.buf, ch)
|
||||
ch = next
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(p.buf, []byte("\\x")) && len(p.buf)%2 == 0 {
|
||||
data := p.buf[2:]
|
||||
buf := make([]byte, hex.DecodedLen(len(data)))
|
||||
n, err := hex.Decode(buf, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf[:n], nil
|
||||
}
|
||||
|
||||
return p.buf, nil
|
||||
}
|
||||
|
||||
func (p *pgparser) ReadRange(ch byte) ([]byte, error) {
|
||||
p.buf = p.buf[:0]
|
||||
p.buf = append(p.buf, ch)
|
||||
|
||||
for p.Valid() {
|
||||
ch = p.Read()
|
||||
p.buf = append(p.buf, ch)
|
||||
if ch == ']' || ch == ')' {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return p.buf, nil
|
||||
}
|
||||
20
vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go
generated
vendored
20
vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package pgdialect
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"reflect"
|
||||
|
|
@ -27,14 +28,6 @@ const (
|
|||
pgTypeSerial = "SERIAL" // 4 byte autoincrementing integer
|
||||
pgTypeBigSerial = "BIGSERIAL" // 8 byte autoincrementing integer
|
||||
|
||||
// Character Types
|
||||
pgTypeChar = "CHAR" // fixed length string (blank padded)
|
||||
pgTypeText = "TEXT" // variable length string without limit
|
||||
|
||||
// JSON Types
|
||||
pgTypeJSON = "JSON" // text representation of json data
|
||||
pgTypeJSONB = "JSONB" // binary representation of json data
|
||||
|
||||
// Binary Data Types
|
||||
pgTypeBytea = "BYTEA" // binary string
|
||||
)
|
||||
|
|
@ -43,6 +36,7 @@ var (
|
|||
ipType = reflect.TypeOf((*net.IP)(nil)).Elem()
|
||||
ipNetType = reflect.TypeOf((*net.IPNet)(nil)).Elem()
|
||||
jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
|
||||
nullStringType = reflect.TypeOf((*sql.NullString)(nil)).Elem()
|
||||
)
|
||||
|
||||
func (d *Dialect) DefaultVarcharLen() int {
|
||||
|
|
@ -78,12 +72,14 @@ func fieldSQLType(field *schema.Field) string {
|
|||
|
||||
func sqlType(typ reflect.Type) string {
|
||||
switch typ {
|
||||
case nullStringType: // typ.Kind() == reflect.Struct, test for exact match
|
||||
return sqltype.VarChar
|
||||
case ipType:
|
||||
return pgTypeInet
|
||||
case ipNetType:
|
||||
return pgTypeCidr
|
||||
case jsonRawMessageType:
|
||||
return pgTypeJSONB
|
||||
return sqltype.JSONB
|
||||
}
|
||||
|
||||
sqlType := schema.DiscoverSQLType(typ)
|
||||
|
|
@ -93,16 +89,16 @@ func sqlType(typ reflect.Type) string {
|
|||
}
|
||||
|
||||
switch typ.Kind() {
|
||||
case reflect.Map, reflect.Struct:
|
||||
case reflect.Map, reflect.Struct: // except typ == nullStringType, see above
|
||||
if sqlType == sqltype.VarChar {
|
||||
return pgTypeJSONB
|
||||
return sqltype.JSONB
|
||||
}
|
||||
return sqlType
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
return pgTypeBytea
|
||||
}
|
||||
return pgTypeJSONB
|
||||
return sqltype.JSONB
|
||||
}
|
||||
|
||||
return sqlType
|
||||
|
|
|
|||
60
vendor/github.com/uptrace/bun/dialect/pgdialect/stream_parser.go
generated
vendored
60
vendor/github.com/uptrace/bun/dialect/pgdialect/stream_parser.go
generated
vendored
|
|
@ -1,60 +0,0 @@
|
|||
package pgdialect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type streamParser struct {
|
||||
b []byte
|
||||
i int
|
||||
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func newStreamParser(b []byte, start int) *streamParser {
|
||||
return &streamParser{
|
||||
b: b,
|
||||
i: start,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *streamParser) valid() bool {
|
||||
return p.i < len(p.b)
|
||||
}
|
||||
|
||||
func (p *streamParser) skipByte(skip byte) error {
|
||||
c, err := p.readByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c == skip {
|
||||
return nil
|
||||
}
|
||||
p.unreadByte()
|
||||
return fmt.Errorf("got %q, wanted %q", c, skip)
|
||||
}
|
||||
|
||||
func (p *streamParser) readByte() (byte, error) {
|
||||
if p.valid() {
|
||||
c := p.b[p.i]
|
||||
p.i++
|
||||
return c, nil
|
||||
}
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func (p *streamParser) unreadByte() {
|
||||
p.i--
|
||||
}
|
||||
|
||||
func (p *streamParser) peek() byte {
|
||||
if p.valid() {
|
||||
return p.b[p.i]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *streamParser) skipNext() {
|
||||
p.i++
|
||||
}
|
||||
2
vendor/github.com/uptrace/bun/dialect/pgdialect/version.go
generated
vendored
2
vendor/github.com/uptrace/bun/dialect/pgdialect/version.go
generated
vendored
|
|
@ -2,5 +2,5 @@ package pgdialect
|
|||
|
||||
// Version is the current release version.
|
||||
func Version() string {
|
||||
return "1.2.1"
|
||||
return "1.2.5"
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go
generated
vendored
2
vendor/github.com/uptrace/bun/dialect/sqlitedialect/version.go
generated
vendored
|
|
@ -2,5 +2,5 @@ package sqlitedialect
|
|||
|
||||
// Version is the current release version.
|
||||
func Version() string {
|
||||
return "1.2.1"
|
||||
return "1.2.5"
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/extra/bunotel/README.md
generated
vendored
2
vendor/github.com/uptrace/bun/extra/bunotel/README.md
generated
vendored
|
|
@ -1,3 +1,3 @@
|
|||
# OpenTelemetry instrumentation for Bun
|
||||
|
||||
See [example](../example/opentelemetry) for details.
|
||||
See [example](../../example/opentelemetry) for details.
|
||||
|
|
|
|||
16
vendor/github.com/uptrace/bun/extra/bunotel/unsafe.go
generated
vendored
16
vendor/github.com/uptrace/bun/extra/bunotel/unsafe.go
generated
vendored
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
package bunotel
|
||||
|
|
@ -5,14 +6,15 @@ package bunotel
|
|||
import "unsafe"
|
||||
|
||||
func bytesToString(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
if len(b) == 0 {
|
||||
return ""
|
||||
}
|
||||
return unsafe.String(&b[0], len(b))
|
||||
}
|
||||
|
||||
func stringToBytes(s string) []byte {
|
||||
return *(*[]byte)(unsafe.Pointer(
|
||||
&struct {
|
||||
string
|
||||
Cap int
|
||||
}{s, len(s)},
|
||||
))
|
||||
if s == "" {
|
||||
return []byte{}
|
||||
}
|
||||
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||
}
|
||||
|
|
|
|||
50
vendor/github.com/uptrace/bun/internal/parser/parser.go
generated
vendored
50
vendor/github.com/uptrace/bun/internal/parser/parser.go
generated
vendored
|
|
@ -2,6 +2,8 @@ package parser
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/uptrace/bun/internal"
|
||||
|
|
@ -22,23 +24,43 @@ func NewString(s string) *Parser {
|
|||
return New(internal.Bytes(s))
|
||||
}
|
||||
|
||||
func (p *Parser) Reset(b []byte) {
|
||||
p.b = b
|
||||
p.i = 0
|
||||
}
|
||||
|
||||
func (p *Parser) Valid() bool {
|
||||
return p.i < len(p.b)
|
||||
}
|
||||
|
||||
func (p *Parser) Bytes() []byte {
|
||||
func (p *Parser) Remaining() []byte {
|
||||
return p.b[p.i:]
|
||||
}
|
||||
|
||||
func (p *Parser) ReadByte() (byte, error) {
|
||||
if p.Valid() {
|
||||
ch := p.b[p.i]
|
||||
p.Advance()
|
||||
return ch, nil
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
func (p *Parser) Read() byte {
|
||||
if p.Valid() {
|
||||
c := p.b[p.i]
|
||||
ch := p.b[p.i]
|
||||
p.Advance()
|
||||
return c
|
||||
return ch
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *Parser) Unread() {
|
||||
if p.i > 0 {
|
||||
p.i--
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) Peek() byte {
|
||||
if p.Valid() {
|
||||
return p.b[p.i]
|
||||
|
|
@ -50,19 +72,25 @@ func (p *Parser) Advance() {
|
|||
p.i++
|
||||
}
|
||||
|
||||
func (p *Parser) Skip(skip byte) bool {
|
||||
if p.Peek() == skip {
|
||||
func (p *Parser) Skip(skip byte) error {
|
||||
ch := p.Peek()
|
||||
if ch == skip {
|
||||
p.Advance()
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
return false
|
||||
return fmt.Errorf("got %q, wanted %q", ch, skip)
|
||||
}
|
||||
|
||||
func (p *Parser) SkipBytes(skip []byte) bool {
|
||||
if len(skip) > len(p.b[p.i:]) {
|
||||
return false
|
||||
func (p *Parser) SkipPrefix(skip []byte) error {
|
||||
if !bytes.HasPrefix(p.b[p.i:], skip) {
|
||||
return fmt.Errorf("got %q, wanted prefix %q", p.b, skip)
|
||||
}
|
||||
if !bytes.Equal(p.b[p.i:p.i+len(skip)], skip) {
|
||||
p.i += len(skip)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) CutPrefix(skip []byte) bool {
|
||||
if !bytes.HasPrefix(p.b[p.i:], skip) {
|
||||
return false
|
||||
}
|
||||
p.i += len(skip)
|
||||
|
|
|
|||
16
vendor/github.com/uptrace/bun/internal/unsafe.go
generated
vendored
16
vendor/github.com/uptrace/bun/internal/unsafe.go
generated
vendored
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
package internal
|
||||
|
|
@ -6,15 +7,16 @@ import "unsafe"
|
|||
|
||||
// String converts byte slice to string.
|
||||
func String(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
if len(b) == 0 {
|
||||
return ""
|
||||
}
|
||||
return unsafe.String(&b[0], len(b))
|
||||
}
|
||||
|
||||
// Bytes converts string to byte slice.
|
||||
func Bytes(s string) []byte {
|
||||
return *(*[]byte)(unsafe.Pointer(
|
||||
&struct {
|
||||
string
|
||||
Cap int
|
||||
}{s, len(s)},
|
||||
))
|
||||
if s == "" {
|
||||
return []byte{}
|
||||
}
|
||||
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/uptrace/bun/migrate/migrations.go
generated
vendored
4
vendor/github.com/uptrace/bun/migrate/migrations.go
generated
vendored
|
|
@ -96,10 +96,6 @@ func (m *Migrations) Discover(fsys fs.FS) error {
|
|||
}
|
||||
|
||||
migration := m.getOrCreateMigration(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
migration.Comment = comment
|
||||
migrationFunc := NewSQLMigrationFunc(fsys, path)
|
||||
|
||||
|
|
|
|||
5
vendor/github.com/uptrace/bun/migrate/migrator.go
generated
vendored
5
vendor/github.com/uptrace/bun/migrate/migrator.go
generated
vendored
|
|
@ -362,7 +362,10 @@ func (m *Migrator) MarkUnapplied(ctx context.Context, migration *Migration) erro
|
|||
}
|
||||
|
||||
func (m *Migrator) TruncateTable(ctx context.Context) error {
|
||||
_, err := m.db.NewTruncateTable().TableExpr(m.table).Exec(ctx)
|
||||
_, err := m.db.NewTruncateTable().
|
||||
Model((*Migration)(nil)).
|
||||
ModelTableExpr(m.table).
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
3
vendor/github.com/uptrace/bun/model_map.go
generated
vendored
3
vendor/github.com/uptrace/bun/model_map.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package bun
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"reflect"
|
||||
|
|
@ -82,6 +83,8 @@ func (m *mapModel) Scan(src interface{}) error {
|
|||
return m.scanRaw(src)
|
||||
case reflect.Slice:
|
||||
if scanType.Elem().Kind() == reflect.Uint8 {
|
||||
// Reference types such as []byte are only valid until the next call to Scan.
|
||||
src := bytes.Clone(src.([]byte))
|
||||
return m.scanRaw(src)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
21
vendor/github.com/uptrace/bun/model_table_has_many.go
generated
vendored
21
vendor/github.com/uptrace/bun/model_table_has_many.go
generated
vendored
|
|
@ -24,7 +24,7 @@ var _ TableModel = (*hasManyModel)(nil)
|
|||
func newHasManyModel(j *relationJoin) *hasManyModel {
|
||||
baseTable := j.BaseModel.Table()
|
||||
joinModel := j.JoinModel.(*sliceTableModel)
|
||||
baseValues := baseValues(joinModel, j.Relation.BaseFields)
|
||||
baseValues := baseValues(joinModel, j.Relation.BasePKs)
|
||||
if len(baseValues) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -92,9 +92,9 @@ func (m *hasManyModel) Scan(src interface{}) error {
|
|||
return err
|
||||
}
|
||||
|
||||
for _, f := range m.rel.JoinFields {
|
||||
for _, f := range m.rel.JoinPKs {
|
||||
if f.Name == field.Name {
|
||||
m.structKey = append(m.structKey, field.Value(m.strct).Interface())
|
||||
m.structKey = append(m.structKey, indirectFieldValue(field.Value(m.strct)))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -103,6 +103,7 @@ func (m *hasManyModel) Scan(src interface{}) error {
|
|||
}
|
||||
|
||||
func (m *hasManyModel) parkStruct() error {
|
||||
|
||||
baseValues, ok := m.baseValues[internal.NewMapKey(m.structKey)]
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
|
|
@ -143,7 +144,19 @@ func baseValues(model TableModel, fields []*schema.Field) map[internal.MapKey][]
|
|||
|
||||
func modelKey(key []interface{}, strct reflect.Value, fields []*schema.Field) []interface{} {
|
||||
for _, f := range fields {
|
||||
key = append(key, f.Value(strct).Interface())
|
||||
key = append(key, indirectFieldValue(f.Value(strct)))
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// indirectFieldValue return the field value dereferencing the pointer if necessary.
|
||||
// The value is then used as a map key.
|
||||
func indirectFieldValue(field reflect.Value) interface{} {
|
||||
if field.Kind() != reflect.Ptr {
|
||||
return field.Interface()
|
||||
}
|
||||
if field.IsNil() {
|
||||
return nil
|
||||
}
|
||||
return field.Elem().Interface()
|
||||
}
|
||||
|
|
|
|||
22
vendor/github.com/uptrace/bun/model_table_m2m.go
generated
vendored
22
vendor/github.com/uptrace/bun/model_table_m2m.go
generated
vendored
|
|
@ -24,7 +24,7 @@ var _ TableModel = (*m2mModel)(nil)
|
|||
func newM2MModel(j *relationJoin) *m2mModel {
|
||||
baseTable := j.BaseModel.Table()
|
||||
joinModel := j.JoinModel.(*sliceTableModel)
|
||||
baseValues := baseValues(joinModel, baseTable.PKs)
|
||||
baseValues := baseValues(joinModel, j.Relation.BasePKs)
|
||||
if len(baseValues) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -83,27 +83,21 @@ func (m *m2mModel) Scan(src interface{}) error {
|
|||
column := m.columns[m.scanIndex]
|
||||
m.scanIndex++
|
||||
|
||||
field, ok := m.table.FieldMap[column]
|
||||
if !ok {
|
||||
// Base pks must come first.
|
||||
if m.scanIndex <= len(m.rel.M2MBasePKs) {
|
||||
return m.scanM2MColumn(column, src)
|
||||
}
|
||||
|
||||
if err := field.ScanValue(m.strct, src); err != nil {
|
||||
return err
|
||||
if field, ok := m.table.FieldMap[column]; ok {
|
||||
return field.ScanValue(m.strct, src)
|
||||
}
|
||||
|
||||
for _, fk := range m.rel.M2MBaseFields {
|
||||
if fk.Name == field.Name {
|
||||
m.structKey = append(m.structKey, field.Value(m.strct).Interface())
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err := m.scanColumn(column, src)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *m2mModel) scanM2MColumn(column string, src interface{}) error {
|
||||
for _, field := range m.rel.M2MBaseFields {
|
||||
for _, field := range m.rel.M2MBasePKs {
|
||||
if field.Name == column {
|
||||
dest := reflect.New(field.IndirectType).Elem()
|
||||
if err := field.Scan(dest, src); err != nil {
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/model_table_struct.go
generated
vendored
2
vendor/github.com/uptrace/bun/model_table_struct.go
generated
vendored
|
|
@ -242,7 +242,7 @@ func (m *structTableModel) ScanRows(ctx context.Context, rows *sql.Rows) (int, e
|
|||
n++
|
||||
|
||||
// And discard the rest. This is especially important for SQLite3, which can return
|
||||
// a row like it was inserted sucessfully and then return an actual error for the next row.
|
||||
// a row like it was inserted successfully and then return an actual error for the next row.
|
||||
// See issues/100.
|
||||
for rows.Next() {
|
||||
n++
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/package.json
generated
vendored
2
vendor/github.com/uptrace/bun/package.json
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gobun",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.5",
|
||||
"main": "index.js",
|
||||
"repository": "git@github.com:uptrace/bun.git",
|
||||
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>",
|
||||
|
|
|
|||
7
vendor/github.com/uptrace/bun/query_base.go
generated
vendored
7
vendor/github.com/uptrace/bun/query_base.go
generated
vendored
|
|
@ -8,6 +8,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun/dialect"
|
||||
"github.com/uptrace/bun/dialect/feature"
|
||||
"github.com/uptrace/bun/internal"
|
||||
"github.com/uptrace/bun/schema"
|
||||
|
|
@ -418,7 +419,11 @@ func (q *baseQuery) _appendTables(
|
|||
} else {
|
||||
b = fmter.AppendQuery(b, string(q.table.SQLNameForSelects))
|
||||
if withAlias && q.table.SQLAlias != q.table.SQLNameForSelects {
|
||||
b = append(b, " AS "...)
|
||||
if q.db.dialect.Name() == dialect.Oracle {
|
||||
b = append(b, ' ')
|
||||
} else {
|
||||
b = append(b, " AS "...)
|
||||
}
|
||||
b = append(b, q.table.SQLAlias...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
48
vendor/github.com/uptrace/bun/query_select.go
generated
vendored
48
vendor/github.com/uptrace/bun/query_select.go
generated
vendored
|
|
@ -538,6 +538,11 @@ func (q *SelectQuery) appendQuery(
|
|||
if count && !cteCount {
|
||||
b = append(b, "count(*)"...)
|
||||
} else {
|
||||
// MSSQL: allows Limit() without Order() as per https://stackoverflow.com/a/36156953
|
||||
if q.limit > 0 && len(q.order) == 0 && fmter.Dialect().Name() == dialect.MSSQL {
|
||||
b = append(b, "0 AS _temp_sort, "...)
|
||||
}
|
||||
|
||||
b, err = q.appendColumns(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -564,8 +569,8 @@ func (q *SelectQuery) appendQuery(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
for _, j := range q.joins {
|
||||
b, err = j.AppendQuery(fmter, b)
|
||||
for _, join := range q.joins {
|
||||
b, err = join.AppendQuery(fmter, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -793,6 +798,12 @@ func (q *SelectQuery) appendOrder(fmter schema.Formatter, b []byte) (_ []byte, e
|
|||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// MSSQL: allows Limit() without Order() as per https://stackoverflow.com/a/36156953
|
||||
if q.limit > 0 && fmter.Dialect().Name() == dialect.MSSQL {
|
||||
return append(b, " ORDER BY _temp_sort"...), nil
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
|
|
@ -856,52 +867,57 @@ func (q *SelectQuery) Exec(ctx context.Context, dest ...interface{}) (res sql.Re
|
|||
}
|
||||
|
||||
func (q *SelectQuery) Scan(ctx context.Context, dest ...interface{}) error {
|
||||
_, err := q.scanResult(ctx, dest...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *SelectQuery) scanResult(ctx context.Context, dest ...interface{}) (sql.Result, error) {
|
||||
if q.err != nil {
|
||||
return q.err
|
||||
return nil, q.err
|
||||
}
|
||||
|
||||
model, err := q.getModel(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if q.table != nil {
|
||||
if err := q.beforeSelectHook(ctx); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := q.beforeAppendModel(ctx, q); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes())
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := internal.String(queryBytes)
|
||||
|
||||
res, err := q.scan(ctx, q, query, model, true)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if n, _ := res.RowsAffected(); n > 0 {
|
||||
if tableModel, ok := model.(TableModel); ok {
|
||||
if err := q.selectJoins(ctx, tableModel.getJoins()); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if q.table != nil {
|
||||
if err := q.afterSelectHook(ctx); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (q *SelectQuery) beforeSelectHook(ctx context.Context) error {
|
||||
|
|
@ -946,6 +962,16 @@ func (q *SelectQuery) Count(ctx context.Context) (int, error) {
|
|||
}
|
||||
|
||||
func (q *SelectQuery) ScanAndCount(ctx context.Context, dest ...interface{}) (int, error) {
|
||||
if q.offset == 0 && q.limit == 0 {
|
||||
// If there is no limit and offset, we can use a single query to get the count and scan
|
||||
if res, err := q.scanResult(ctx, dest...); err != nil {
|
||||
return 0, err
|
||||
} else if n, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return int(n), nil
|
||||
}
|
||||
}
|
||||
if _, ok := q.conn.(*DB); ok {
|
||||
return q.scanAndCountConc(ctx, dest...)
|
||||
}
|
||||
|
|
|
|||
13
vendor/github.com/uptrace/bun/query_table_create.go
generated
vendored
13
vendor/github.com/uptrace/bun/query_table_create.go
generated
vendored
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/uptrace/bun/dialect"
|
||||
"github.com/uptrace/bun/dialect/feature"
|
||||
"github.com/uptrace/bun/dialect/sqltype"
|
||||
"github.com/uptrace/bun/internal"
|
||||
|
|
@ -165,7 +166,7 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by
|
|||
b = append(b, field.SQLName...)
|
||||
b = append(b, " "...)
|
||||
b = q.appendSQLType(b, field)
|
||||
if field.NotNull {
|
||||
if field.NotNull && q.db.dialect.Name() != dialect.Oracle {
|
||||
b = append(b, " NOT NULL"...)
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +247,11 @@ func (q *CreateTableQuery) appendSQLType(b []byte, field *schema.Field) []byte {
|
|||
return append(b, field.CreateTableSQLType...)
|
||||
}
|
||||
|
||||
b = append(b, sqltype.VarChar...)
|
||||
if q.db.dialect.Name() == dialect.Oracle {
|
||||
b = append(b, "VARCHAR2"...)
|
||||
} else {
|
||||
b = append(b, sqltype.VarChar...)
|
||||
}
|
||||
b = append(b, "("...)
|
||||
b = strconv.AppendInt(b, int64(q.varchar), 10)
|
||||
b = append(b, ")"...)
|
||||
|
|
@ -297,9 +302,9 @@ func (q *CreateTableQuery) appendFKConstraintsRel(fmter schema.Formatter, b []by
|
|||
b, err = q.appendFK(fmter, b, schema.QueryWithArgs{
|
||||
Query: "(?) REFERENCES ? (?) ? ?",
|
||||
Args: []interface{}{
|
||||
Safe(appendColumns(nil, "", rel.BaseFields)),
|
||||
Safe(appendColumns(nil, "", rel.BasePKs)),
|
||||
rel.JoinTable.SQLName,
|
||||
Safe(appendColumns(nil, "", rel.JoinFields)),
|
||||
Safe(appendColumns(nil, "", rel.JoinPKs)),
|
||||
Safe(rel.OnUpdate),
|
||||
Safe(rel.OnDelete),
|
||||
},
|
||||
|
|
|
|||
5
vendor/github.com/uptrace/bun/query_table_truncate.go
generated
vendored
5
vendor/github.com/uptrace/bun/query_table_truncate.go
generated
vendored
|
|
@ -57,6 +57,11 @@ func (q *TruncateTableQuery) TableExpr(query string, args ...interface{}) *Trunc
|
|||
return q
|
||||
}
|
||||
|
||||
func (q *TruncateTableQuery) ModelTableExpr(query string, args ...interface{}) *TruncateTableQuery {
|
||||
q.modelTableName = schema.SafeQuery(query, args)
|
||||
return q
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func (q *TruncateTableQuery) ContinueIdentity() *TruncateTableQuery {
|
||||
|
|
|
|||
32
vendor/github.com/uptrace/bun/relation_join.go
generated
vendored
32
vendor/github.com/uptrace/bun/relation_join.go
generated
vendored
|
|
@ -70,11 +70,11 @@ func (j *relationJoin) manyQuery(q *SelectQuery) *SelectQuery {
|
|||
}
|
||||
|
||||
func (j *relationJoin) manyQueryCompositeIn(where []byte, q *SelectQuery) *SelectQuery {
|
||||
if len(j.Relation.JoinFields) > 1 {
|
||||
if len(j.Relation.JoinPKs) > 1 {
|
||||
where = append(where, '(')
|
||||
}
|
||||
where = appendColumns(where, j.JoinModel.Table().SQLAlias, j.Relation.JoinFields)
|
||||
if len(j.Relation.JoinFields) > 1 {
|
||||
where = appendColumns(where, j.JoinModel.Table().SQLAlias, j.Relation.JoinPKs)
|
||||
if len(j.Relation.JoinPKs) > 1 {
|
||||
where = append(where, ')')
|
||||
}
|
||||
where = append(where, " IN ("...)
|
||||
|
|
@ -83,7 +83,7 @@ func (j *relationJoin) manyQueryCompositeIn(where []byte, q *SelectQuery) *Selec
|
|||
where,
|
||||
j.JoinModel.rootValue(),
|
||||
j.JoinModel.parentIndex(),
|
||||
j.Relation.BaseFields,
|
||||
j.Relation.BasePKs,
|
||||
)
|
||||
where = append(where, ")"...)
|
||||
q = q.Where(internal.String(where))
|
||||
|
|
@ -104,8 +104,8 @@ func (j *relationJoin) manyQueryMulti(where []byte, q *SelectQuery) *SelectQuery
|
|||
where,
|
||||
j.JoinModel.rootValue(),
|
||||
j.JoinModel.parentIndex(),
|
||||
j.Relation.BaseFields,
|
||||
j.Relation.JoinFields,
|
||||
j.Relation.BasePKs,
|
||||
j.Relation.JoinPKs,
|
||||
j.JoinModel.Table().SQLAlias,
|
||||
)
|
||||
|
||||
|
|
@ -175,10 +175,10 @@ func (j *relationJoin) m2mQuery(q *SelectQuery) *SelectQuery {
|
|||
q = q.Model(m2mModel)
|
||||
|
||||
index := j.JoinModel.parentIndex()
|
||||
baseTable := j.BaseModel.Table()
|
||||
|
||||
if j.Relation.M2MTable != nil {
|
||||
fields := append(j.Relation.M2MBaseFields, j.Relation.M2MJoinFields...)
|
||||
// We only need base pks to park joined models to the base model.
|
||||
fields := j.Relation.M2MBasePKs
|
||||
|
||||
b := make([]byte, 0, len(fields))
|
||||
b = appendColumns(b, j.Relation.M2MTable.SQLAlias, fields)
|
||||
|
|
@ -193,7 +193,7 @@ func (j *relationJoin) m2mQuery(q *SelectQuery) *SelectQuery {
|
|||
join = append(join, " AS "...)
|
||||
join = append(join, j.Relation.M2MTable.SQLAlias...)
|
||||
join = append(join, " ON ("...)
|
||||
for i, col := range j.Relation.M2MBaseFields {
|
||||
for i, col := range j.Relation.M2MBasePKs {
|
||||
if i > 0 {
|
||||
join = append(join, ", "...)
|
||||
}
|
||||
|
|
@ -202,13 +202,13 @@ func (j *relationJoin) m2mQuery(q *SelectQuery) *SelectQuery {
|
|||
join = append(join, col.SQLName...)
|
||||
}
|
||||
join = append(join, ") IN ("...)
|
||||
join = appendChildValues(fmter, join, j.BaseModel.rootValue(), index, baseTable.PKs)
|
||||
join = appendChildValues(fmter, join, j.BaseModel.rootValue(), index, j.Relation.BasePKs)
|
||||
join = append(join, ")"...)
|
||||
q = q.Join(internal.String(join))
|
||||
|
||||
joinTable := j.JoinModel.Table()
|
||||
for i, m2mJoinField := range j.Relation.M2MJoinFields {
|
||||
joinField := j.Relation.JoinFields[i]
|
||||
for i, m2mJoinField := range j.Relation.M2MJoinPKs {
|
||||
joinField := j.Relation.JoinPKs[i]
|
||||
q = q.Where("?.? = ?.?",
|
||||
joinTable.SQLAlias, joinField.SQLName,
|
||||
j.Relation.M2MTable.SQLAlias, m2mJoinField.SQLName)
|
||||
|
|
@ -310,13 +310,13 @@ func (j *relationJoin) appendHasOneJoin(
|
|||
b = append(b, " ON "...)
|
||||
|
||||
b = append(b, '(')
|
||||
for i, baseField := range j.Relation.BaseFields {
|
||||
for i, baseField := range j.Relation.BasePKs {
|
||||
if i > 0 {
|
||||
b = append(b, " AND "...)
|
||||
}
|
||||
b = j.appendAlias(fmter, b)
|
||||
b = append(b, '.')
|
||||
b = append(b, j.Relation.JoinFields[i].SQLName...)
|
||||
b = append(b, j.Relation.JoinPKs[i].SQLName...)
|
||||
b = append(b, " = "...)
|
||||
b = j.appendBaseAlias(fmter, b)
|
||||
b = append(b, '.')
|
||||
|
|
@ -367,13 +367,13 @@ func appendChildValues(
|
|||
}
|
||||
|
||||
// appendMultiValues is an alternative to appendChildValues that doesn't use the sql keyword ID
|
||||
// but instead use a old style ((k1=v1) AND (k2=v2)) OR (...) of conditions.
|
||||
// but instead uses old style ((k1=v1) AND (k2=v2)) OR (...) conditions.
|
||||
func appendMultiValues(
|
||||
fmter schema.Formatter, b []byte, v reflect.Value, index []int, baseFields, joinFields []*schema.Field, joinTable schema.Safe,
|
||||
) []byte {
|
||||
// This is based on a mix of appendChildValues and query_base.appendColumns
|
||||
|
||||
// These should never missmatch in length but nice to know if it does
|
||||
// These should never mismatch in length but nice to know if it does
|
||||
if len(joinFields) != len(baseFields) {
|
||||
panic("not reached")
|
||||
}
|
||||
|
|
|
|||
29
vendor/github.com/uptrace/bun/schema/append_value.go
generated
vendored
29
vendor/github.com/uptrace/bun/schema/append_value.go
generated
vendored
|
|
@ -7,9 +7,9 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
"github.com/uptrace/bun/dialect"
|
||||
"github.com/uptrace/bun/dialect/sqltype"
|
||||
"github.com/uptrace/bun/extra/bunjson"
|
||||
|
|
@ -51,7 +51,7 @@ var appenders = []AppenderFunc{
|
|||
reflect.UnsafePointer: nil,
|
||||
}
|
||||
|
||||
var appenderMap sync.Map
|
||||
var appenderCache = xsync.NewMapOf[reflect.Type, AppenderFunc]()
|
||||
|
||||
func FieldAppender(dialect Dialect, field *Field) AppenderFunc {
|
||||
if field.Tag.HasOption("msgpack") {
|
||||
|
|
@ -67,7 +67,7 @@ func FieldAppender(dialect Dialect, field *Field) AppenderFunc {
|
|||
}
|
||||
|
||||
if fieldType.Kind() != reflect.Ptr {
|
||||
if reflect.PtrTo(fieldType).Implements(driverValuerType) {
|
||||
if reflect.PointerTo(fieldType).Implements(driverValuerType) {
|
||||
return addrAppender(appendDriverValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -79,14 +79,14 @@ func FieldAppender(dialect Dialect, field *Field) AppenderFunc {
|
|||
}
|
||||
|
||||
func Appender(dialect Dialect, typ reflect.Type) AppenderFunc {
|
||||
if v, ok := appenderMap.Load(typ); ok {
|
||||
return v.(AppenderFunc)
|
||||
if v, ok := appenderCache.Load(typ); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
fn := appender(dialect, typ)
|
||||
|
||||
if v, ok := appenderMap.LoadOrStore(typ, fn); ok {
|
||||
return v.(AppenderFunc)
|
||||
if v, ok := appenderCache.LoadOrStore(typ, fn); ok {
|
||||
return v
|
||||
}
|
||||
return fn
|
||||
}
|
||||
|
|
@ -99,10 +99,10 @@ func appender(dialect Dialect, typ reflect.Type) AppenderFunc {
|
|||
return appendTimeValue
|
||||
case timePtrType:
|
||||
return PtrAppender(appendTimeValue)
|
||||
case ipType:
|
||||
return appendIPValue
|
||||
case ipNetType:
|
||||
return appendIPNetValue
|
||||
case ipType, netipPrefixType, netipAddrType:
|
||||
return appendStringer
|
||||
case jsonRawMessageType:
|
||||
return appendJSONRawMessageValue
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ func appender(dialect Dialect, typ reflect.Type) AppenderFunc {
|
|||
}
|
||||
|
||||
if kind != reflect.Ptr {
|
||||
ptr := reflect.PtrTo(typ)
|
||||
ptr := reflect.PointerTo(typ)
|
||||
if ptr.Implements(queryAppenderType) {
|
||||
return addrAppender(appendQueryAppenderValue)
|
||||
}
|
||||
|
|
@ -247,16 +247,15 @@ func appendTimeValue(fmter Formatter, b []byte, v reflect.Value) []byte {
|
|||
return fmter.Dialect().AppendTime(b, tm)
|
||||
}
|
||||
|
||||
func appendIPValue(fmter Formatter, b []byte, v reflect.Value) []byte {
|
||||
ip := v.Interface().(net.IP)
|
||||
return fmter.Dialect().AppendString(b, ip.String())
|
||||
}
|
||||
|
||||
func appendIPNetValue(fmter Formatter, b []byte, v reflect.Value) []byte {
|
||||
ipnet := v.Interface().(net.IPNet)
|
||||
return fmter.Dialect().AppendString(b, ipnet.String())
|
||||
}
|
||||
|
||||
func appendStringer(fmter Formatter, b []byte, v reflect.Value) []byte {
|
||||
return fmter.Dialect().AppendString(b, v.Interface().(fmt.Stringer).String())
|
||||
}
|
||||
|
||||
func appendJSONRawMessageValue(fmter Formatter, b []byte, v reflect.Value) []byte {
|
||||
bytes := v.Bytes()
|
||||
if bytes == nil {
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/schema/dialect.go
generated
vendored
2
vendor/github.com/uptrace/bun/schema/dialect.go
generated
vendored
|
|
@ -118,7 +118,7 @@ func (BaseDialect) AppendJSON(b, jsonb []byte) []byte {
|
|||
case '\000':
|
||||
continue
|
||||
case '\\':
|
||||
if p.SkipBytes([]byte("u0000")) {
|
||||
if p.CutPrefix([]byte("u0000")) {
|
||||
b = append(b, `\\u0000`...)
|
||||
} else {
|
||||
b = append(b, '\\')
|
||||
|
|
|
|||
3
vendor/github.com/uptrace/bun/schema/reflect.go
generated
vendored
3
vendor/github.com/uptrace/bun/schema/reflect.go
generated
vendored
|
|
@ -4,6 +4,7 @@ import (
|
|||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/netip"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -14,6 +15,8 @@ var (
|
|||
timeType = timePtrType.Elem()
|
||||
ipType = reflect.TypeOf((*net.IP)(nil)).Elem()
|
||||
ipNetType = reflect.TypeOf((*net.IPNet)(nil)).Elem()
|
||||
netipPrefixType = reflect.TypeOf((*netip.Prefix)(nil)).Elem()
|
||||
netipAddrType = reflect.TypeOf((*netip.Addr)(nil)).Elem()
|
||||
jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
|
||||
|
||||
driverValuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
|
||||
|
|
|
|||
26
vendor/github.com/uptrace/bun/schema/relation.go
generated
vendored
26
vendor/github.com/uptrace/bun/schema/relation.go
generated
vendored
|
|
@ -13,21 +13,25 @@ const (
|
|||
)
|
||||
|
||||
type Relation struct {
|
||||
Type int
|
||||
Field *Field
|
||||
JoinTable *Table
|
||||
BaseFields []*Field
|
||||
JoinFields []*Field
|
||||
OnUpdate string
|
||||
OnDelete string
|
||||
Condition []string
|
||||
// Base and Join can be explained with this query:
|
||||
//
|
||||
// SELECT * FROM base_table JOIN join_table
|
||||
|
||||
Type int
|
||||
Field *Field
|
||||
JoinTable *Table
|
||||
BasePKs []*Field
|
||||
JoinPKs []*Field
|
||||
OnUpdate string
|
||||
OnDelete string
|
||||
Condition []string
|
||||
|
||||
PolymorphicField *Field
|
||||
PolymorphicValue string
|
||||
|
||||
M2MTable *Table
|
||||
M2MBaseFields []*Field
|
||||
M2MJoinFields []*Field
|
||||
M2MTable *Table
|
||||
M2MBasePKs []*Field
|
||||
M2MJoinPKs []*Field
|
||||
}
|
||||
|
||||
// References returns true if the table to which the Relation belongs needs to declare a foreign key constraint to create the relation.
|
||||
|
|
|
|||
14
vendor/github.com/uptrace/bun/schema/scan.go
generated
vendored
14
vendor/github.com/uptrace/bun/schema/scan.go
generated
vendored
|
|
@ -8,9 +8,9 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
|
||||
"github.com/uptrace/bun/dialect/sqltype"
|
||||
|
|
@ -53,7 +53,7 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
var scannerMap sync.Map
|
||||
var scannerCache = xsync.NewMapOf[reflect.Type, ScannerFunc]()
|
||||
|
||||
func FieldScanner(dialect Dialect, field *Field) ScannerFunc {
|
||||
if field.Tag.HasOption("msgpack") {
|
||||
|
|
@ -72,14 +72,14 @@ func FieldScanner(dialect Dialect, field *Field) ScannerFunc {
|
|||
}
|
||||
|
||||
func Scanner(typ reflect.Type) ScannerFunc {
|
||||
if v, ok := scannerMap.Load(typ); ok {
|
||||
return v.(ScannerFunc)
|
||||
if v, ok := scannerCache.Load(typ); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
fn := scanner(typ)
|
||||
|
||||
if v, ok := scannerMap.LoadOrStore(typ, fn); ok {
|
||||
return v.(ScannerFunc)
|
||||
if v, ok := scannerCache.LoadOrStore(typ, fn); ok {
|
||||
return v
|
||||
}
|
||||
return fn
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ func scanner(typ reflect.Type) ScannerFunc {
|
|||
}
|
||||
|
||||
if kind != reflect.Ptr {
|
||||
ptr := reflect.PtrTo(typ)
|
||||
ptr := reflect.PointerTo(typ)
|
||||
if ptr.Implements(scannerType) {
|
||||
return addrScanner(scanScanner)
|
||||
}
|
||||
|
|
|
|||
86
vendor/github.com/uptrace/bun/schema/table.go
generated
vendored
86
vendor/github.com/uptrace/bun/schema/table.go
generated
vendored
|
|
@ -74,16 +74,7 @@ type structField struct {
|
|||
Table *Table
|
||||
}
|
||||
|
||||
func newTable(
|
||||
dialect Dialect, typ reflect.Type, seen map[reflect.Type]*Table, canAddr bool,
|
||||
) *Table {
|
||||
if table, ok := seen[typ]; ok {
|
||||
return table
|
||||
}
|
||||
|
||||
table := new(Table)
|
||||
seen[typ] = table
|
||||
|
||||
func (table *Table) init(dialect Dialect, typ reflect.Type, canAddr bool) {
|
||||
table.dialect = dialect
|
||||
table.Type = typ
|
||||
table.ZeroValue = reflect.New(table.Type).Elem()
|
||||
|
|
@ -97,7 +88,7 @@ func newTable(
|
|||
|
||||
table.Fields = make([]*Field, 0, typ.NumField())
|
||||
table.FieldMap = make(map[string]*Field, typ.NumField())
|
||||
table.processFields(typ, seen, canAddr)
|
||||
table.processFields(typ, canAddr)
|
||||
|
||||
hooks := []struct {
|
||||
typ reflect.Type
|
||||
|
|
@ -109,28 +100,15 @@ func newTable(
|
|||
{afterScanRowHookType, afterScanRowHookFlag},
|
||||
}
|
||||
|
||||
typ = reflect.PtrTo(table.Type)
|
||||
typ = reflect.PointerTo(table.Type)
|
||||
for _, hook := range hooks {
|
||||
if typ.Implements(hook.typ) {
|
||||
table.flags = table.flags.Set(hook.flag)
|
||||
}
|
||||
}
|
||||
|
||||
return table
|
||||
}
|
||||
|
||||
func (t *Table) init() {
|
||||
for _, field := range t.relFields {
|
||||
t.processRelation(field)
|
||||
}
|
||||
t.relFields = nil
|
||||
}
|
||||
|
||||
func (t *Table) processFields(
|
||||
typ reflect.Type,
|
||||
seen map[reflect.Type]*Table,
|
||||
canAddr bool,
|
||||
) {
|
||||
func (t *Table) processFields(typ reflect.Type, canAddr bool) {
|
||||
type embeddedField struct {
|
||||
prefix string
|
||||
index []int
|
||||
|
|
@ -172,7 +150,7 @@ func (t *Table) processFields(
|
|||
continue
|
||||
}
|
||||
|
||||
subtable := newTable(t.dialect, sfType, seen, canAddr)
|
||||
subtable := t.dialect.Tables().InProgress(sfType)
|
||||
|
||||
for _, subfield := range subtable.allFields {
|
||||
embedded = append(embedded, embeddedField{
|
||||
|
|
@ -206,7 +184,7 @@ func (t *Table) processFields(
|
|||
t.TypeName, sf.Name, fieldType.Kind()))
|
||||
}
|
||||
|
||||
subtable := newTable(t.dialect, fieldType, seen, canAddr)
|
||||
subtable := t.dialect.Tables().InProgress(fieldType)
|
||||
for _, subfield := range subtable.allFields {
|
||||
embedded = append(embedded, embeddedField{
|
||||
prefix: prefix,
|
||||
|
|
@ -229,7 +207,7 @@ func (t *Table) processFields(
|
|||
}
|
||||
t.StructMap[field.Name] = &structField{
|
||||
Index: field.Index,
|
||||
Table: newTable(t.dialect, field.IndirectType, seen, canAddr),
|
||||
Table: t.dialect.Tables().InProgress(field.IndirectType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -423,6 +401,10 @@ func (t *Table) newField(sf reflect.StructField, tag tagparser.Tag) *Field {
|
|||
sqlName = tag.Name
|
||||
}
|
||||
|
||||
if s, ok := tag.Option("column"); ok {
|
||||
sqlName = s
|
||||
}
|
||||
|
||||
for name := range tag.Options {
|
||||
if !isKnownFieldOption(name) {
|
||||
internal.Warn.Printf("%s.%s has unknown tag option: %q", t.TypeName, sf.Name, name)
|
||||
|
|
@ -490,6 +472,13 @@ func (t *Table) newField(sf reflect.StructField, tag tagparser.Tag) *Field {
|
|||
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
func (t *Table) initRelations() {
|
||||
for _, field := range t.relFields {
|
||||
t.processRelation(field)
|
||||
}
|
||||
t.relFields = nil
|
||||
}
|
||||
|
||||
func (t *Table) processRelation(field *Field) {
|
||||
if rel, ok := field.Tag.Option("rel"); ok {
|
||||
t.initRelation(field, rel)
|
||||
|
|
@ -577,7 +566,7 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
|
|||
joinColumn := joinColumns[i]
|
||||
|
||||
if f := t.FieldMap[baseColumn]; f != nil {
|
||||
rel.BaseFields = append(rel.BaseFields, f)
|
||||
rel.BasePKs = append(rel.BasePKs, f)
|
||||
} else {
|
||||
panic(fmt.Errorf(
|
||||
"bun: %s belongs-to %s: %s must have column %s",
|
||||
|
|
@ -586,7 +575,7 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
|
|||
}
|
||||
|
||||
if f := joinTable.FieldMap[joinColumn]; f != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, f)
|
||||
rel.JoinPKs = append(rel.JoinPKs, f)
|
||||
} else {
|
||||
panic(fmt.Errorf(
|
||||
"bun: %s belongs-to %s: %s must have column %s",
|
||||
|
|
@ -597,17 +586,17 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
|
|||
return rel
|
||||
}
|
||||
|
||||
rel.JoinFields = joinTable.PKs
|
||||
rel.JoinPKs = joinTable.PKs
|
||||
fkPrefix := internal.Underscore(field.GoName) + "_"
|
||||
for _, joinPK := range joinTable.PKs {
|
||||
fkName := fkPrefix + joinPK.Name
|
||||
if fk := t.FieldMap[fkName]; fk != nil {
|
||||
rel.BaseFields = append(rel.BaseFields, fk)
|
||||
rel.BasePKs = append(rel.BasePKs, fk)
|
||||
continue
|
||||
}
|
||||
|
||||
if fk := t.FieldMap[joinPK.Name]; fk != nil {
|
||||
rel.BaseFields = append(rel.BaseFields, fk)
|
||||
rel.BasePKs = append(rel.BasePKs, fk)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -640,7 +629,7 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
|||
baseColumns, joinColumns := parseRelationJoin(join)
|
||||
for i, baseColumn := range baseColumns {
|
||||
if f := t.FieldMap[baseColumn]; f != nil {
|
||||
rel.BaseFields = append(rel.BaseFields, f)
|
||||
rel.BasePKs = append(rel.BasePKs, f)
|
||||
} else {
|
||||
panic(fmt.Errorf(
|
||||
"bun: %s has-one %s: %s must have column %s",
|
||||
|
|
@ -650,7 +639,7 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
|||
|
||||
joinColumn := joinColumns[i]
|
||||
if f := joinTable.FieldMap[joinColumn]; f != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, f)
|
||||
rel.JoinPKs = append(rel.JoinPKs, f)
|
||||
} else {
|
||||
panic(fmt.Errorf(
|
||||
"bun: %s has-one %s: %s must have column %s",
|
||||
|
|
@ -661,17 +650,17 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
|||
return rel
|
||||
}
|
||||
|
||||
rel.BaseFields = t.PKs
|
||||
rel.BasePKs = t.PKs
|
||||
fkPrefix := internal.Underscore(t.ModelName) + "_"
|
||||
for _, pk := range t.PKs {
|
||||
fkName := fkPrefix + pk.Name
|
||||
if f := joinTable.FieldMap[fkName]; f != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, f)
|
||||
rel.JoinPKs = append(rel.JoinPKs, f)
|
||||
continue
|
||||
}
|
||||
|
||||
if f := joinTable.FieldMap[pk.Name]; f != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, f)
|
||||
rel.JoinPKs = append(rel.JoinPKs, f)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -720,7 +709,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
|||
}
|
||||
|
||||
if f := t.FieldMap[baseColumn]; f != nil {
|
||||
rel.BaseFields = append(rel.BaseFields, f)
|
||||
rel.BasePKs = append(rel.BasePKs, f)
|
||||
} else {
|
||||
panic(fmt.Errorf(
|
||||
"bun: %s has-many %s: %s must have column %s",
|
||||
|
|
@ -729,7 +718,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
|||
}
|
||||
|
||||
if f := joinTable.FieldMap[joinColumn]; f != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, f)
|
||||
rel.JoinPKs = append(rel.JoinPKs, f)
|
||||
} else {
|
||||
panic(fmt.Errorf(
|
||||
"bun: %s has-many %s: %s must have column %s",
|
||||
|
|
@ -738,7 +727,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
rel.BaseFields = t.PKs
|
||||
rel.BasePKs = t.PKs
|
||||
fkPrefix := internal.Underscore(t.ModelName) + "_"
|
||||
if isPolymorphic {
|
||||
polymorphicColumn = fkPrefix + "type"
|
||||
|
|
@ -747,12 +736,12 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
|||
for _, pk := range t.PKs {
|
||||
joinColumn := fkPrefix + pk.Name
|
||||
if fk := joinTable.FieldMap[joinColumn]; fk != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, fk)
|
||||
rel.JoinPKs = append(rel.JoinPKs, fk)
|
||||
continue
|
||||
}
|
||||
|
||||
if fk := joinTable.FieldMap[pk.Name]; fk != nil {
|
||||
rel.JoinFields = append(rel.JoinFields, fk)
|
||||
rel.JoinPKs = append(rel.JoinPKs, fk)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -852,12 +841,12 @@ func (t *Table) m2mRelation(field *Field) *Relation {
|
|||
}
|
||||
|
||||
leftRel := m2mTable.belongsToRelation(leftField)
|
||||
rel.BaseFields = leftRel.JoinFields
|
||||
rel.M2MBaseFields = leftRel.BaseFields
|
||||
rel.BasePKs = leftRel.JoinPKs
|
||||
rel.M2MBasePKs = leftRel.BasePKs
|
||||
|
||||
rightRel := m2mTable.belongsToRelation(rightField)
|
||||
rel.JoinFields = rightRel.JoinFields
|
||||
rel.M2MJoinFields = rightRel.BaseFields
|
||||
rel.JoinPKs = rightRel.JoinPKs
|
||||
rel.M2MJoinPKs = rightRel.BasePKs
|
||||
|
||||
return rel
|
||||
}
|
||||
|
|
@ -918,6 +907,7 @@ func isKnownFieldOption(name string) bool {
|
|||
"array",
|
||||
"hstore",
|
||||
"composite",
|
||||
"multirange",
|
||||
"json_use_number",
|
||||
"msgpack",
|
||||
"notnull",
|
||||
|
|
|
|||
104
vendor/github.com/uptrace/bun/schema/tables.go
generated
vendored
104
vendor/github.com/uptrace/bun/schema/tables.go
generated
vendored
|
|
@ -4,22 +4,24 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
)
|
||||
|
||||
type Tables struct {
|
||||
dialect Dialect
|
||||
tables sync.Map
|
||||
|
||||
mu sync.RWMutex
|
||||
seen map[reflect.Type]*Table
|
||||
inProgress map[reflect.Type]*tableInProgress
|
||||
mu sync.Mutex
|
||||
tables *xsync.MapOf[reflect.Type, *Table]
|
||||
|
||||
inProgress map[reflect.Type]*Table
|
||||
}
|
||||
|
||||
func NewTables(dialect Dialect) *Tables {
|
||||
return &Tables{
|
||||
dialect: dialect,
|
||||
seen: make(map[reflect.Type]*Table),
|
||||
inProgress: make(map[reflect.Type]*tableInProgress),
|
||||
tables: xsync.NewMapOf[reflect.Type, *Table](),
|
||||
inProgress: make(map[reflect.Type]*Table),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,58 +32,26 @@ func (t *Tables) Register(models ...interface{}) {
|
|||
}
|
||||
|
||||
func (t *Tables) Get(typ reflect.Type) *Table {
|
||||
return t.table(typ, false)
|
||||
}
|
||||
|
||||
func (t *Tables) InProgress(typ reflect.Type) *Table {
|
||||
return t.table(typ, true)
|
||||
}
|
||||
|
||||
func (t *Tables) table(typ reflect.Type, allowInProgress bool) *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.(*Table)
|
||||
return v
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if v, ok := t.tables.Load(typ); ok {
|
||||
t.mu.Unlock()
|
||||
return v.(*Table)
|
||||
return v
|
||||
}
|
||||
|
||||
var table *Table
|
||||
|
||||
inProgress := t.inProgress[typ]
|
||||
if inProgress == nil {
|
||||
table = newTable(t.dialect, typ, t.seen, false)
|
||||
inProgress = newTableInProgress(table)
|
||||
t.inProgress[typ] = inProgress
|
||||
} else {
|
||||
table = inProgress.table
|
||||
}
|
||||
|
||||
t.mu.Unlock()
|
||||
|
||||
if allowInProgress {
|
||||
return table
|
||||
}
|
||||
|
||||
if !inProgress.init() {
|
||||
return table
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
delete(t.inProgress, typ)
|
||||
t.tables.Store(typ, table)
|
||||
t.mu.Unlock()
|
||||
table := t.InProgress(typ)
|
||||
table.initRelations()
|
||||
|
||||
t.dialect.OnTable(table)
|
||||
|
||||
for _, field := range table.FieldMap {
|
||||
if field.UserSQLType == "" {
|
||||
field.UserSQLType = field.DiscoveredSQLType
|
||||
|
|
@ -91,15 +61,27 @@ func (t *Tables) table(typ reflect.Type, allowInProgress bool) *Table {
|
|||
}
|
||||
}
|
||||
|
||||
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, false)
|
||||
|
||||
return table
|
||||
}
|
||||
|
||||
func (t *Tables) ByModel(name string) *Table {
|
||||
var found *Table
|
||||
t.tables.Range(func(key, value interface{}) bool {
|
||||
t := value.(*Table)
|
||||
if t.TypeName == name {
|
||||
found = t
|
||||
t.tables.Range(func(typ reflect.Type, table *Table) bool {
|
||||
if table.TypeName == name {
|
||||
found = table
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
@ -109,34 +91,12 @@ func (t *Tables) ByModel(name string) *Table {
|
|||
|
||||
func (t *Tables) ByName(name string) *Table {
|
||||
var found *Table
|
||||
t.tables.Range(func(key, value interface{}) bool {
|
||||
t := value.(*Table)
|
||||
if t.Name == name {
|
||||
found = t
|
||||
t.tables.Range(func(typ reflect.Type, table *Table) bool {
|
||||
if table.Name == name {
|
||||
found = table
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
type tableInProgress struct {
|
||||
table *Table
|
||||
|
||||
initOnce sync.Once
|
||||
}
|
||||
|
||||
func newTableInProgress(table *Table) *tableInProgress {
|
||||
return &tableInProgress{
|
||||
table: table,
|
||||
}
|
||||
}
|
||||
|
||||
func (inp *tableInProgress) init() bool {
|
||||
var inited bool
|
||||
inp.initOnce.Do(func() {
|
||||
inp.table.init()
|
||||
inited = true
|
||||
})
|
||||
return inited
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/schema/zerochecker.go
generated
vendored
2
vendor/github.com/uptrace/bun/schema/zerochecker.go
generated
vendored
|
|
@ -60,7 +60,7 @@ func zeroChecker(typ reflect.Type) IsZeroerFunc {
|
|||
kind := typ.Kind()
|
||||
|
||||
if kind != reflect.Ptr {
|
||||
ptr := reflect.PtrTo(typ)
|
||||
ptr := reflect.PointerTo(typ)
|
||||
if ptr.Implements(isZeroerType) {
|
||||
return addrChecker(isZeroInterface)
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/bun/version.go
generated
vendored
2
vendor/github.com/uptrace/bun/version.go
generated
vendored
|
|
@ -2,5 +2,5 @@ package bun
|
|||
|
||||
// Version is the current release version.
|
||||
func Version() string {
|
||||
return "1.2.1"
|
||||
return "1.2.5"
|
||||
}
|
||||
|
|
|
|||
5
vendor/github.com/uptrace/opentelemetry-go-extra/otelsql/README.md
generated
vendored
5
vendor/github.com/uptrace/opentelemetry-go-extra/otelsql/README.md
generated
vendored
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
# database/sql instrumentation for OpenTelemetry Go
|
||||
|
||||
[database/sql OpenTelemetry instrumentation](https://uptrace.dev/getinstrument/opentelemetry-database-sql.html)
|
||||
records database queries (including `Tx` and `Stmt` queries) and reports `DBStats` metrics.
|
||||
[OpenTelemetry database/sql](https://uptrace.dev/get/instrument/opentelemetry-database-sql.html)
|
||||
instrumentation records database queries (including `Tx` and `Stmt` queries) and reports `DBStats`
|
||||
metrics.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
|||
2
vendor/github.com/uptrace/opentelemetry-go-extra/otelsql/version.go
generated
vendored
2
vendor/github.com/uptrace/opentelemetry-go-extra/otelsql/version.go
generated
vendored
|
|
@ -2,5 +2,5 @@ package otelsql
|
|||
|
||||
// Version is the current release version.
|
||||
func Version() string {
|
||||
return "0.2.4"
|
||||
return "0.3.2"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue