diff options
Diffstat (limited to 'vendor/github.com/uptrace')
40 files changed, 822 insertions, 463 deletions
diff --git a/vendor/github.com/uptrace/bun/.prettierrc.yaml b/vendor/github.com/uptrace/bun/.prettierrc.yml index decea5634..decea5634 100644 --- a/vendor/github.com/uptrace/bun/.prettierrc.yaml +++ b/vendor/github.com/uptrace/bun/.prettierrc.yml diff --git a/vendor/github.com/uptrace/bun/CHANGELOG.md b/vendor/github.com/uptrace/bun/CHANGELOG.md index a0221c225..5e738f2ea 100644 --- a/vendor/github.com/uptrace/bun/CHANGELOG.md +++ b/vendor/github.com/uptrace/bun/CHANGELOG.md @@ -1,58 +1,141 @@ -## [1.0.9](https://github.com/uptrace/bun/compare/v1.0.8...v1.0.9) (2021-09-27) +## [1.0.14](https://github.com/uptrace/bun/compare/v1.0.13...v1.0.14) (2021-10-24) ### Bug Fixes -* change DBStats to use uint32 instead of uint64 to make it work on i386 ([caca2a7](https://github.com/uptrace/bun/commit/caca2a7130288dec49fa26b49c8550140ee52f4c)) +* correct binary serialization for mysql ([#259](https://github.com/uptrace/bun/issues/259)) ([e899f50](https://github.com/uptrace/bun/commit/e899f50b22ef6759ef8c029a6cd3f25f2bde17ef)) +* correctly escape single quotes in pg arrays ([3010847](https://github.com/uptrace/bun/commit/3010847f5c2c50bce1969689a0b77fd8a6fb7e55)) +* use BLOB sql type to encode []byte in MySQL and SQLite ([725ec88](https://github.com/uptrace/bun/commit/725ec8843824a7fc8f4058ead75ab0e62a78192a)) ### Features -* add IQuery and QueryEvent.IQuery ([b762942](https://github.com/uptrace/bun/commit/b762942fa3b1d8686d0a559f93f2a6847b83d9c1)) -* add QueryEvent.Model ([7688201](https://github.com/uptrace/bun/commit/7688201b485d14d3e393956f09a3200ea4d4e31d)) -* **bunotel:** add experimental bun.query.timing metric ([2cdb384](https://github.com/uptrace/bun/commit/2cdb384678631ccadac0fb75f524bd5e91e96ee2)) -* **pgdriver:** add Config.ConnParams to session config params ([408caf0](https://github.com/uptrace/bun/commit/408caf0bb579e23e26fc6149efd6851814c22517)) -* **pgdriver:** allow specifying timeout in DSN ([7dbc71b](https://github.com/uptrace/bun/commit/7dbc71b3494caddc2e97d113f00067071b9e19da)) +* warn when there are args but no placeholders ([06dde21](https://github.com/uptrace/bun/commit/06dde215c8d0bde2b2364597190729a160e536a1)) -## [1.0.8](https://github.com/uptrace/bun/compare/v1.0.7...v1.0.8) (2021-09-18) +## [1.0.13](https://github.com/uptrace/bun/compare/v1.0.12...v1.0.13) (2021-10-17) + +### Breaking Change + +- **pgdriver:** enable TLS by default with InsecureSkipVerify=true + ([15ec635](https://github.com/uptrace/bun/commit/15ec6356a04d5cf62d2efbeb189610532dc5eb31)) +### Features + +- add BeforeAppendModelHook + ([0b55de7](https://github.com/uptrace/bun/commit/0b55de77aaffc1ed0894ef16f45df77bca7d93c1)) +- **pgdriver:** add support for unix socket DSN + ([f398cec](https://github.com/uptrace/bun/commit/f398cec1c3873efdf61ac0b94ebe06c657f0cf91)) + +## [1.0.12](https://github.com/uptrace/bun/compare/v1.0.11...v1.0.12) (2021-10-14) ### Bug Fixes -* don't append soft delete where for insert queries with on conflict clause ([27c477c](https://github.com/uptrace/bun/commit/27c477ce071d4c49c99a2531d638ed9f20e33461)) -* improve bun.NullTime to accept string ([73ad6f5](https://github.com/uptrace/bun/commit/73ad6f5640a0a9b09f8df2bc4ab9cb510021c50c)) -* make allowzero work with auto-detected primary keys ([82ca87c](https://github.com/uptrace/bun/commit/82ca87c7c49797d507b31fdaacf8343716d4feff)) -* support soft deletes on nil model ([0556e3c](https://github.com/uptrace/bun/commit/0556e3c63692a7f4e48659d52b55ffd9cca0202a)) +- add InsertQuery.ColumnExpr to specify columns + ([60ffe29](https://github.com/uptrace/bun/commit/60ffe293b37912d95f28e69734ff51edf4b27da7)) +- **bundebug:** change WithVerbose to accept a bool flag + ([b2f8b91](https://github.com/uptrace/bun/commit/b2f8b912de1dc29f40c79066de1e9d6379db666c)) +- **pgdialect:** fix bytea[] handling + ([a5ca013](https://github.com/uptrace/bun/commit/a5ca013742c5a2e947b43d13f9c2fc0cf6a65d9c)) +- **pgdriver:** rename DriverOption to Option + ([51c1702](https://github.com/uptrace/bun/commit/51c1702431787d7369904b2624e346bf3e59c330)) +- support allowzero on the soft delete field + ([d0abec7](https://github.com/uptrace/bun/commit/d0abec71a9a546472a83bd70ed4e6a7357659a9b)) +### Features +- **bundebug:** allow to configure the hook using env var, for example, BUNDEBUG={0,1,2} + ([ce92852](https://github.com/uptrace/bun/commit/ce928524cab9a83395f3772ae9dd5d7732af281d)) +- **bunotel:** report DBStats metrics + ([b9b1575](https://github.com/uptrace/bun/commit/b9b15750f405cdbd345b776f5a56c6f742bc7361)) +- **pgdriver:** add Error.StatementTimeout + ([8a7934d](https://github.com/uptrace/bun/commit/8a7934dd788057828bb2b0983732b4394b74e960)) +- **pgdriver:** allow setting Network in config + ([b24b5d8](https://github.com/uptrace/bun/commit/b24b5d8014195a56ad7a4c634c10681038e6044d)) -## [1.0.7](https://github.com/uptrace/bun/compare/v1.0.6...v1.0.7) (2021-09-15) +## [1.0.11](https://github.com/uptrace/bun/compare/v1.0.10...v1.0.11) (2021-10-05) + +### Bug Fixes + +- **mysqldialect:** remove duplicate AppendTime + ([8d42090](https://github.com/uptrace/bun/commit/8d42090af34a1760004482c7fc0923b114d79937)) +## [1.0.10](https://github.com/uptrace/bun/compare/v1.0.9...v1.0.10) (2021-10-05) ### Bug Fixes -* don't append zero time as NULL without nullzero tag ([3b8d9cb](https://github.com/uptrace/bun/commit/3b8d9cb4e39eb17f79a618396bbbe0adbc66b07b)) -* **pgdriver:** return PostgreSQL DATE as a string ([40be0e8](https://github.com/uptrace/bun/commit/40be0e8ea85f8932b7a410a6fc2dd3acd2d18ebc)) -* specify table alias for soft delete where ([5fff1dc](https://github.com/uptrace/bun/commit/5fff1dc1dd74fa48623a24fa79e358a544dfac0b)) +- add UpdateQuery.OmitZero + ([2294db6](https://github.com/uptrace/bun/commit/2294db61d228711435fff1075409a30086b37555)) +- make ExcludeColumn work with many-to-many queries + ([300e12b](https://github.com/uptrace/bun/commit/300e12b993554ff839ec4fa6bbea97e16aca1b55)) +- **mysqldialect:** append time in local timezone + ([e763cc8](https://github.com/uptrace/bun/commit/e763cc81eac4b11fff4e074ad3ff6cd970a71697)) +- **tagparser:** improve parsing options with brackets + ([0daa61e](https://github.com/uptrace/bun/commit/0daa61edc3c4d927ed260332b99ee09f4bb6b42f)) +### Features + +- add timetz parsing + ([6e415c4](https://github.com/uptrace/bun/commit/6e415c4c5fa2c8caf4bb4aed4e5897fe5676f5a5)) + +## [1.0.9](https://github.com/uptrace/bun/compare/v1.0.8...v1.0.9) (2021-09-27) + +### Bug Fixes + +- change DBStats to use uint32 instead of uint64 to make it work on i386 + ([caca2a7](https://github.com/uptrace/bun/commit/caca2a7130288dec49fa26b49c8550140ee52f4c)) ### Features -* add SelectQuery.Exists helper ([c3e59c1](https://github.com/uptrace/bun/commit/c3e59c1bc58b43c4b8e33e7d170ad33a08fbc3c7)) +- add IQuery and QueryEvent.IQuery + ([b762942](https://github.com/uptrace/bun/commit/b762942fa3b1d8686d0a559f93f2a6847b83d9c1)) +- add QueryEvent.Model + ([7688201](https://github.com/uptrace/bun/commit/7688201b485d14d3e393956f09a3200ea4d4e31d)) +- **bunotel:** add experimental bun.query.timing metric + ([2cdb384](https://github.com/uptrace/bun/commit/2cdb384678631ccadac0fb75f524bd5e91e96ee2)) +- **pgdriver:** add Config.ConnParams to session config params + ([408caf0](https://github.com/uptrace/bun/commit/408caf0bb579e23e26fc6149efd6851814c22517)) +- **pgdriver:** allow specifying timeout in DSN + ([7dbc71b](https://github.com/uptrace/bun/commit/7dbc71b3494caddc2e97d113f00067071b9e19da)) +## [1.0.8](https://github.com/uptrace/bun/compare/v1.0.7...v1.0.8) (2021-09-18) +### Bug Fixes -## [1.0.6](https://github.com/uptrace/bun/compare/v1.0.5...v1.0.6) (2021-09-11) +- don't append soft delete where for insert queries with on conflict clause + ([27c477c](https://github.com/uptrace/bun/commit/27c477ce071d4c49c99a2531d638ed9f20e33461)) +- improve bun.NullTime to accept string + ([73ad6f5](https://github.com/uptrace/bun/commit/73ad6f5640a0a9b09f8df2bc4ab9cb510021c50c)) +- make allowzero work with auto-detected primary keys + ([82ca87c](https://github.com/uptrace/bun/commit/82ca87c7c49797d507b31fdaacf8343716d4feff)) +- support soft deletes on nil model + ([0556e3c](https://github.com/uptrace/bun/commit/0556e3c63692a7f4e48659d52b55ffd9cca0202a)) +## [1.0.7](https://github.com/uptrace/bun/compare/v1.0.6...v1.0.7) (2021-09-15) ### Bug Fixes -* change unique tag to create a separate unique constraint ([8401615](https://github.com/uptrace/bun/commit/84016155a77ca77613cc054277fefadae3098757)) -* improve zero checker for ptr values ([2b3623d](https://github.com/uptrace/bun/commit/2b3623dd665d873911fd20ca707016929921e862)) +- don't append zero time as NULL without nullzero tag + ([3b8d9cb](https://github.com/uptrace/bun/commit/3b8d9cb4e39eb17f79a618396bbbe0adbc66b07b)) +- **pgdriver:** return PostgreSQL DATE as a string + ([40be0e8](https://github.com/uptrace/bun/commit/40be0e8ea85f8932b7a410a6fc2dd3acd2d18ebc)) +- specify table alias for soft delete where + ([5fff1dc](https://github.com/uptrace/bun/commit/5fff1dc1dd74fa48623a24fa79e358a544dfac0b)) + +### Features + +- add SelectQuery.Exists helper + ([c3e59c1](https://github.com/uptrace/bun/commit/c3e59c1bc58b43c4b8e33e7d170ad33a08fbc3c7)) +## [1.0.6](https://github.com/uptrace/bun/compare/v1.0.5...v1.0.6) (2021-09-11) + +### Bug Fixes +- change unique tag to create a separate unique constraint + ([8401615](https://github.com/uptrace/bun/commit/84016155a77ca77613cc054277fefadae3098757)) +- improve zero checker for ptr values + ([2b3623d](https://github.com/uptrace/bun/commit/2b3623dd665d873911fd20ca707016929921e862)) ## v1.0.5 - Sep 09 2021 diff --git a/vendor/github.com/uptrace/bun/CONTRIBUTING.md b/vendor/github.com/uptrace/bun/CONTRIBUTING.md index 7c435b5ac..03e79cdc4 100644 --- a/vendor/github.com/uptrace/bun/CONTRIBUTING.md +++ b/vendor/github.com/uptrace/bun/CONTRIBUTING.md @@ -12,7 +12,7 @@ cd internal/dbtest 1. Run `release.sh` script which updates versions in go.mod files and pushes a new branch to GitHub: ```shell -./scripts/release.sh -t v1.0.0 +TAG=v1.0.0 ./scripts/release.sh ``` 2. Open a pull request and wait for the build to finish. @@ -20,11 +20,5 @@ cd internal/dbtest 3. Merge the pull request and run `tag.sh` to create tags for packages: ```shell -./scripts/tag.sh -t v1.0.0 -``` - -4. Push the tags: - -```shell -git push origin --tags +TAG=v1.0.0 ./scripts/tag.sh ``` diff --git a/vendor/github.com/uptrace/bun/bun.go b/vendor/github.com/uptrace/bun/bun.go index 0b1969b26..2a788c4c1 100644 --- a/vendor/github.com/uptrace/bun/bun.go +++ b/vendor/github.com/uptrace/bun/bun.go @@ -15,9 +15,17 @@ type ( NullTime = schema.NullTime BaseModel = schema.BaseModel + Query = schema.Query + BeforeAppendModelHook = schema.BeforeAppendModelHook + + BeforeScanRowHook = schema.BeforeScanRowHook + AfterScanRowHook = schema.AfterScanRowHook + + // DEPRECATED. Use BeforeScanRowHook instead. BeforeScanHook = schema.BeforeScanHook - AfterScanHook = schema.AfterScanHook + // DEPRECATED. Use AfterScanRowHook instead. + AfterScanHook = schema.AfterScanHook ) type BeforeSelectHook interface { diff --git a/vendor/github.com/uptrace/bun/db.go b/vendor/github.com/uptrace/bun/db.go index 97c3f2dfa..72fe118a9 100644 --- a/vendor/github.com/uptrace/bun/db.go +++ b/vendor/github.com/uptrace/bun/db.go @@ -163,7 +163,14 @@ func (db *DB) ScanRow(ctx context.Context, rows *sql.Rows, dest ...interface{}) return rs.ScanRow(ctx, rows) } +type queryHookIniter interface { + Init(db *DB) +} + func (db *DB) AddQueryHook(hook QueryHook) { + if initer, ok := hook.(queryHookIniter); ok { + initer.Init(db) + } db.queryHooks = append(db.queryHooks, hook) } diff --git a/vendor/github.com/uptrace/bun/dialect/append.go b/vendor/github.com/uptrace/bun/dialect/append.go index 01e80745a..c9d137946 100644 --- a/vendor/github.com/uptrace/bun/dialect/append.go +++ b/vendor/github.com/uptrace/bun/dialect/append.go @@ -4,11 +4,9 @@ import ( "encoding/hex" "math" "strconv" - "time" "unicode/utf8" "github.com/uptrace/bun/internal" - "github.com/uptrace/bun/internal/parser" ) func AppendError(b []byte, err error) []byte { @@ -78,55 +76,16 @@ func AppendString(b []byte, s string) []byte { return b } -func AppendBytes(b []byte, bytes []byte) []byte { - if bytes == nil { +func AppendBytes(b, bs []byte) []byte { + if bs == nil { return AppendNull(b) } b = append(b, `'\x`...) s := len(b) - b = append(b, make([]byte, hex.EncodedLen(len(bytes)))...) - hex.Encode(b[s:], bytes) - - b = append(b, '\'') - - return b -} - -func AppendTime(b []byte, tm time.Time) []byte { - b = append(b, '\'') - b = tm.UTC().AppendFormat(b, "2006-01-02 15:04:05.999999-07:00") - b = append(b, '\'') - return b -} - -func AppendJSON(b, jsonb []byte) []byte { - b = append(b, '\'') - - p := parser.New(jsonb) - for p.Valid() { - c := p.Read() - switch c { - case '"': - b = append(b, '"') - case '\'': - b = append(b, "''"...) - case '\000': - continue - case '\\': - if p.SkipBytes([]byte("u0000")) { - b = append(b, `\\u0000`...) - } else { - b = append(b, '\\') - if p.Valid() { - b = append(b, p.Read()) - } - } - default: - b = append(b, c) - } - } + b = append(b, make([]byte, hex.EncodedLen(len(bs)))...) + hex.Encode(b[s:], bs) b = append(b, '\'') diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go index e8480b6be..d5e0d0a57 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/append.go @@ -2,6 +2,7 @@ package pgdialect import ( "database/sql/driver" + "encoding/hex" "fmt" "reflect" "strconv" @@ -28,26 +29,6 @@ var ( sliceFloat64Type = reflect.TypeOf([]float64(nil)) ) -func customAppender(typ reflect.Type) schema.AppenderFunc { - switch typ.Kind() { - case reflect.Uint32: - return appendUint32ValueAsInt - case reflect.Uint, reflect.Uint64: - return appendUint64ValueAsInt - } - return nil -} - -func appendUint32ValueAsInt(fmter schema.Formatter, b []byte, v reflect.Value) []byte { - return strconv.AppendInt(b, int64(int32(v.Uint())), 10) -} - -func appendUint64ValueAsInt(fmter schema.Formatter, b []byte, v reflect.Value) []byte { - return strconv.AppendInt(b, int64(v.Uint()), 10) -} - -//------------------------------------------------------------------------------ - func arrayAppend(fmter schema.Formatter, b []byte, v interface{}) []byte { switch v := v.(type) { case int64: @@ -57,31 +38,25 @@ func arrayAppend(fmter schema.Formatter, b []byte, v interface{}) []byte { case bool: return dialect.AppendBool(b, v) case []byte: - return dialect.AppendBytes(b, v) + return arrayAppendBytes(b, v) case string: return arrayAppendString(b, v) case time.Time: - return dialect.AppendTime(b, v) + return fmter.Dialect().AppendTime(b, v) default: err := fmt.Errorf("pgdialect: can't append %T", v) return dialect.AppendError(b, err) } } -func arrayElemAppender(typ reflect.Type) schema.AppenderFunc { - if typ.Kind() == reflect.String { - return arrayAppendStringValue - } - if typ.Implements(driverValuerType) { - return arrayAppendDriverValue - } - return schema.Appender(typ, customAppender) -} - 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 { @@ -92,12 +67,12 @@ func arrayAppendDriverValue(fmter schema.Formatter, b []byte, v reflect.Value) [ //------------------------------------------------------------------------------ -func arrayAppender(typ reflect.Type) schema.AppenderFunc { +func (d *Dialect) arrayAppender(typ reflect.Type) schema.AppenderFunc { kind := typ.Kind() switch kind { case reflect.Ptr: - if fn := arrayAppender(typ.Elem()); fn != nil { + if fn := d.arrayAppender(typ.Elem()); fn != nil { return schema.PtrAppender(fn) } case reflect.Slice, reflect.Array: @@ -121,7 +96,7 @@ func arrayAppender(typ reflect.Type) schema.AppenderFunc { } } - appendElem := arrayElemAppender(elemType) + appendElem := d.arrayElemAppender(elemType) if appendElem == nil { panic(fmt.Errorf("pgdialect: %s is not supported", typ)) } @@ -159,6 +134,21 @@ func arrayAppender(typ reflect.Type) schema.AppenderFunc { } } +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) @@ -273,6 +263,22 @@ func appendFloat64Slice(b []byte, floats []float64) []byte { //------------------------------------------------------------------------------ +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 { @@ -280,7 +286,7 @@ func arrayAppendString(b []byte, s string) []byte { case 0: // ignore case '\'': - b = append(b, "'''"...) + b = append(b, "''"...) case '"': b = append(b, '\\', '"') case '\\': diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/array.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/array.go index 57f5a4384..281cff733 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/array.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/array.go @@ -30,7 +30,7 @@ func Array(vi interface{}) *ArrayValue { return &ArrayValue{ v: v, - append: arrayAppender(v.Type()), + append: pgDialect.arrayAppender(v.Type()), scan: arrayScanner(v.Type()), } } diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go index 1c927fca0..0dff754f8 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/array_parser.go @@ -2,6 +2,7 @@ package pgdialect import ( "bytes" + "encoding/hex" "fmt" "io" ) @@ -109,11 +110,29 @@ func (p *arrayParser) readSubstring() ([]byte, error) { } 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 } diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go index 837c2d8ab..bac38972f 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go @@ -2,10 +2,7 @@ package pgdialect import ( "database/sql" - "reflect" "strconv" - "sync" - "time" "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/dialect/feature" @@ -13,12 +10,13 @@ import ( "github.com/uptrace/bun/schema" ) +var pgDialect = New() + type Dialect struct { + schema.BaseDialect + tables *schema.Tables features feature.Feature - - appenderMap sync.Map - scannerMap sync.Map } func New() *Dialect { @@ -71,7 +69,7 @@ func (d *Dialect) onField(field *schema.Field) { } if field.Tag.HasOption("array") { - field.Append = arrayAppender(field.StructField.Type) + field.Append = d.arrayAppender(field.StructField.Type) field.Scan = arrayScanner(field.StructField.Type) } } @@ -80,72 +78,10 @@ func (d *Dialect) IdentQuote() byte { return '"' } -func (d *Dialect) Append(fmter schema.Formatter, b []byte, v interface{}) []byte { - switch v := v.(type) { - case nil: - return dialect.AppendNull(b) - case bool: - return dialect.AppendBool(b, v) - case int: - return strconv.AppendInt(b, int64(v), 10) - case int32: - return strconv.AppendInt(b, int64(v), 10) - case int64: - return strconv.AppendInt(b, v, 10) - case uint: - return strconv.AppendInt(b, int64(v), 10) - case uint32: - return strconv.AppendInt(b, int64(v), 10) - case uint64: - return strconv.AppendInt(b, int64(v), 10) - case float32: - return dialect.AppendFloat32(b, v) - case float64: - return dialect.AppendFloat64(b, v) - case string: - return dialect.AppendString(b, v) - case time.Time: - return dialect.AppendTime(b, v) - case []byte: - return dialect.AppendBytes(b, v) - case schema.QueryAppender: - return schema.AppendQueryAppender(fmter, b, v) - default: - vv := reflect.ValueOf(v) - if vv.Kind() == reflect.Ptr && vv.IsNil() { - return dialect.AppendNull(b) - } - appender := d.Appender(vv.Type()) - return appender(fmter, b, vv) - } +func (d *Dialect) AppendUint32(b []byte, n uint32) []byte { + return strconv.AppendInt(b, int64(int32(n)), 10) } -func (d *Dialect) Appender(typ reflect.Type) schema.AppenderFunc { - if v, ok := d.appenderMap.Load(typ); ok { - return v.(schema.AppenderFunc) - } - - fn := schema.Appender(typ, customAppender) - - if v, ok := d.appenderMap.LoadOrStore(typ, fn); ok { - return v.(schema.AppenderFunc) - } - return fn -} - -func (d *Dialect) FieldAppender(field *schema.Field) schema.AppenderFunc { - return schema.FieldAppender(d, field) -} - -func (d *Dialect) Scanner(typ reflect.Type) schema.ScannerFunc { - if v, ok := d.scannerMap.Load(typ); ok { - return v.(schema.ScannerFunc) - } - - fn := scanner(typ) - - if v, ok := d.scannerMap.LoadOrStore(typ, fn); ok { - return v.(schema.ScannerFunc) - } - return fn +func (d *Dialect) AppendUint64(b []byte, n uint64) []byte { + return strconv.AppendInt(b, int64(n), 10) } diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go index 4c2d8075d..dab0446ed 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go @@ -68,6 +68,10 @@ func fieldSQLType(field *schema.Field) string { } } + if field.DiscoveredSQLType == sqltype.Blob { + return pgTypeBytea + } + return sqlType(field.IndirectType) } diff --git a/vendor/github.com/uptrace/bun/dialect/sqlitedialect/dialect.go b/vendor/github.com/uptrace/bun/dialect/sqlitedialect/dialect.go index 32fd8d3fa..74b278a5d 100644 --- a/vendor/github.com/uptrace/bun/dialect/sqlitedialect/dialect.go +++ b/vendor/github.com/uptrace/bun/dialect/sqlitedialect/dialect.go @@ -2,8 +2,7 @@ package sqlitedialect import ( "database/sql" - "reflect" - "sync" + "encoding/hex" "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/dialect/feature" @@ -12,11 +11,10 @@ import ( ) type Dialect struct { + schema.BaseDialect + tables *schema.Tables features feature.Feature - - appenderMap sync.Map - scannerMap sync.Map } func New() *Dialect { @@ -50,48 +48,36 @@ func (d *Dialect) OnTable(table *schema.Table) { } func (d *Dialect) onField(field *schema.Field) { - // INTEGER PRIMARY KEY is an alias for the ROWID. - // It is safe to convert all ints to INTEGER, because SQLite types don't have size. - switch field.DiscoveredSQLType { - case sqltype.SmallInt, sqltype.BigInt: - field.DiscoveredSQLType = sqltype.Integer - } + field.DiscoveredSQLType = fieldSQLType(field) } func (d *Dialect) IdentQuote() byte { return '"' } -func (d *Dialect) Append(fmter schema.Formatter, b []byte, v interface{}) []byte { - return schema.Append(fmter, b, v, nil) -} - -func (d *Dialect) Appender(typ reflect.Type) schema.AppenderFunc { - if v, ok := d.appenderMap.Load(typ); ok { - return v.(schema.AppenderFunc) +func (d *Dialect) AppendBytes(b []byte, bs []byte) []byte { + if bs == nil { + return dialect.AppendNull(b) } - fn := schema.Appender(typ, nil) + b = append(b, `X'`...) - if v, ok := d.appenderMap.LoadOrStore(typ, fn); ok { - return v.(schema.AppenderFunc) - } - return fn -} - -func (d *Dialect) FieldAppender(field *schema.Field) schema.AppenderFunc { - return schema.FieldAppender(d, field) -} + s := len(b) + b = append(b, make([]byte, hex.EncodedLen(len(bs)))...) + hex.Encode(b[s:], bs) -func (d *Dialect) Scanner(typ reflect.Type) schema.ScannerFunc { - if v, ok := d.scannerMap.Load(typ); ok { - return v.(schema.ScannerFunc) - } + b = append(b, '\'') - fn := scanner(typ) + return b +} - if v, ok := d.scannerMap.LoadOrStore(typ, fn); ok { - return v.(schema.ScannerFunc) +func fieldSQLType(field *schema.Field) string { + switch field.DiscoveredSQLType { + case sqltype.SmallInt, sqltype.BigInt: + // INTEGER PRIMARY KEY is an alias for the ROWID. + // It is safe to convert all ints to INTEGER, because SQLite types don't have size. + return sqltype.Integer + default: + return field.DiscoveredSQLType } - return fn } diff --git a/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go b/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go index 84a51d26d..f58b2f1d1 100644 --- a/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go +++ b/vendor/github.com/uptrace/bun/dialect/sqltype/sqltype.go @@ -8,6 +8,7 @@ const ( Real = "REAL" DoublePrecision = "DOUBLE PRECISION" VarChar = "VARCHAR" + Blob = "BLOB" Timestamp = "TIMESTAMP" JSON = "JSON" JSONB = "JSONB" diff --git a/vendor/github.com/uptrace/bun/hook.go b/vendor/github.com/uptrace/bun/hook.go index 7b60d2a28..7cca7ef6a 100644 --- a/vendor/github.com/uptrace/bun/hook.go +++ b/vendor/github.com/uptrace/bun/hook.go @@ -3,7 +3,6 @@ package bun import ( "context" "database/sql" - "reflect" "strings" "sync/atomic" "time" @@ -11,18 +10,11 @@ import ( "github.com/uptrace/bun/schema" ) -type IQuery interface { - schema.QueryAppender - Operation() string - GetModel() Model - GetTableName() string -} - type QueryEvent struct { DB *DB QueryAppender schema.QueryAppender // Deprecated: use IQuery instead - IQuery IQuery + IQuery Query Query string QueryArgs []interface{} Model Model @@ -58,7 +50,7 @@ type QueryHook interface { func (db *DB) beforeQuery( ctx context.Context, - iquery IQuery, + iquery Query, query string, queryArgs []interface{}, model Model, @@ -116,13 +108,3 @@ func (db *DB) afterQueryFromIndex(ctx context.Context, event *QueryEvent, hookIn db.queryHooks[hookIndex].AfterQuery(ctx, event) } } - -//------------------------------------------------------------------------------ - -func callBeforeScanHook(ctx context.Context, v reflect.Value) error { - return v.Interface().(schema.BeforeScanHook).BeforeScan(ctx) -} - -func callAfterScanHook(ctx context.Context, v reflect.Value) error { - return v.Interface().(schema.AfterScanHook).AfterScan(ctx) -} diff --git a/vendor/github.com/uptrace/bun/internal/tagparser/parser.go b/vendor/github.com/uptrace/bun/internal/tagparser/parser.go index 8ef89248c..eb3246536 100644 --- a/vendor/github.com/uptrace/bun/internal/tagparser/parser.go +++ b/vendor/github.com/uptrace/bun/internal/tagparser/parser.go @@ -93,6 +93,8 @@ func (p *parser) parseValue() string { return p.parseQuotedValue() case ',': return p.s[start : p.i-1] + case '(': + p.skipPairs('(', ')') } } @@ -125,6 +127,23 @@ func (p *parser) parseQuotedValue() string { return "" } +func (p *parser) skipPairs(start, end byte) { + var lvl int + for p.valid() { + switch c := p.read(); c { + case '"': + _ = p.parseQuotedValue() + case start: + lvl++ + case end: + if lvl == 0 { + return + } + lvl-- + } + } +} + func (p *parser) valid() bool { return p.i < len(p.s) } diff --git a/vendor/github.com/uptrace/bun/internal/time.go b/vendor/github.com/uptrace/bun/internal/time.go index e4e0804b0..2cb69b46a 100644 --- a/vendor/github.com/uptrace/bun/internal/time.go +++ b/vendor/github.com/uptrace/bun/internal/time.go @@ -8,34 +8,54 @@ import ( const ( dateFormat = "2006-01-02" timeFormat = "15:04:05.999999999" + timetzFormat1 = "15:04:05.999999999-07:00:00" + timetzFormat2 = "15:04:05.999999999-07:00" + timetzFormat3 = "15:04:05.999999999-07" timestampFormat = "2006-01-02 15:04:05.999999999" - timestamptzFormat = "2006-01-02 15:04:05.999999999-07:00:00" + timestamptzFormat1 = "2006-01-02 15:04:05.999999999-07:00:00" timestamptzFormat2 = "2006-01-02 15:04:05.999999999-07:00" timestamptzFormat3 = "2006-01-02 15:04:05.999999999-07" ) func ParseTime(s string) (time.Time, error) { - switch l := len(s); { - case l < len("15:04:05"): - return time.Time{}, fmt.Errorf("bun: can't parse time=%q", s) - case l <= len(timeFormat): - if s[2] == ':' { - return time.ParseInLocation(timeFormat, s, time.UTC) - } - return time.ParseInLocation(dateFormat, s, time.UTC) - default: - if s[10] == 'T' { + l := len(s) + + if l >= len("2006-01-02 15:04:05") { + switch s[10] { + case ' ': + if c := s[l-6]; c == '+' || c == '-' { + return time.Parse(timestamptzFormat2, s) + } + if c := s[l-3]; c == '+' || c == '-' { + return time.Parse(timestamptzFormat3, s) + } + if c := s[l-9]; c == '+' || c == '-' { + return time.Parse(timestamptzFormat1, s) + } + return time.ParseInLocation(timestampFormat, s, time.UTC) + case 'T': return time.Parse(time.RFC3339Nano, s) } - if c := s[l-9]; c == '+' || c == '-' { - return time.Parse(timestamptzFormat, s) - } + } + + if l >= len("15:04:05-07") { if c := s[l-6]; c == '+' || c == '-' { - return time.Parse(timestamptzFormat2, s) + return time.Parse(timetzFormat2, s) } if c := s[l-3]; c == '+' || c == '-' { - return time.Parse(timestamptzFormat3, s) + return time.Parse(timetzFormat3, s) } - return time.ParseInLocation(timestampFormat, s, time.UTC) + if c := s[l-9]; c == '+' || c == '-' { + return time.Parse(timetzFormat1, s) + } + } + + if l < len("15:04:05") { + return time.Time{}, fmt.Errorf("bun: can't parse time=%q", s) + } + + if s[2] == ':' { + return time.ParseInLocation(timeFormat, s, time.UTC) } + return time.ParseInLocation(dateFormat, s, time.UTC) } diff --git a/vendor/github.com/uptrace/bun/migrate/migration.go b/vendor/github.com/uptrace/bun/migrate/migration.go index 87881d6a2..7d2d318eb 100644 --- a/vendor/github.com/uptrace/bun/migrate/migration.go +++ b/vendor/github.com/uptrace/bun/migrate/migration.go @@ -126,7 +126,11 @@ func init() { } ` -const sqlTemplate = `SELECT 1 +const sqlTemplate = `SET statement_timeout = 0; + +--bun:split + +SELECT 1 --bun:split diff --git a/vendor/github.com/uptrace/bun/model.go b/vendor/github.com/uptrace/bun/model.go index 71a3a1e60..88ec48992 100644 --- a/vendor/github.com/uptrace/bun/model.go +++ b/vendor/github.com/uptrace/bun/model.go @@ -15,10 +15,7 @@ var errNilModel = errors.New("bun: Model(nil)") var timeType = reflect.TypeOf((*time.Time)(nil)).Elem() -type Model interface { - ScanRows(ctx context.Context, rows *sql.Rows) (int, error) - Value() interface{} -} +type Model = schema.Model type rowScanner interface { ScanRow(ctx context.Context, rows *sql.Rows) error @@ -27,8 +24,9 @@ type rowScanner interface { type TableModel interface { Model - schema.BeforeScanHook - schema.AfterScanHook + schema.BeforeAppendModelHook + schema.BeforeScanRowHook + schema.AfterScanRowHook ScanColumn(column string, src interface{}) error Table() *schema.Table diff --git a/vendor/github.com/uptrace/bun/model_map.go b/vendor/github.com/uptrace/bun/model_map.go index 7262ddbc1..814d636e6 100644 --- a/vendor/github.com/uptrace/bun/model_map.go +++ b/vendor/github.com/uptrace/bun/model_map.go @@ -139,7 +139,7 @@ func (m *mapModel) appendColumnsValues(fmter schema.Formatter, b []byte) []byte if isTemplate { b = append(b, '?') } else { - b = fmter.Dialect().Append(fmter, b, m.m[k]) + b = schema.Append(fmter, b, m.m[k]) } } @@ -167,7 +167,7 @@ func (m *mapModel) appendSet(fmter schema.Formatter, b []byte) []byte { if isTemplate { b = append(b, '?') } else { - b = fmter.Dialect().Append(fmter, b, m.m[k]) + b = schema.Append(fmter, b, m.m[k]) } } diff --git a/vendor/github.com/uptrace/bun/model_map_slice.go b/vendor/github.com/uptrace/bun/model_map_slice.go index 1e578db50..1e96c898c 100644 --- a/vendor/github.com/uptrace/bun/model_map_slice.go +++ b/vendor/github.com/uptrace/bun/model_map_slice.go @@ -129,7 +129,7 @@ func (m *mapSliceModel) appendValues(fmter schema.Formatter, b []byte) (_ []byte if j > 0 { b = append(b, ", "...) } - b = fmter.Dialect().Append(fmter, b, el[key]) + b = schema.Append(fmter, b, el[key]) } } diff --git a/vendor/github.com/uptrace/bun/model_scan.go b/vendor/github.com/uptrace/bun/model_scan.go index 2ac22fbb0..48149c4b6 100644 --- a/vendor/github.com/uptrace/bun/model_scan.go +++ b/vendor/github.com/uptrace/bun/model_scan.go @@ -4,6 +4,8 @@ import ( "context" "database/sql" "reflect" + + "github.com/uptrace/bun/schema" ) type scanModel struct { @@ -49,6 +51,6 @@ func (m *scanModel) Scan(src interface{}) error { dest := reflect.ValueOf(m.dest[m.scanIndex]) m.scanIndex++ - scanner := m.db.dialect.Scanner(dest.Type()) + scanner := schema.Scanner(dest.Type()) return scanner(dest, src) } diff --git a/vendor/github.com/uptrace/bun/model_table_slice.go b/vendor/github.com/uptrace/bun/model_table_slice.go index b312b663d..32e48c0dc 100644 --- a/vendor/github.com/uptrace/bun/model_table_slice.go +++ b/vendor/github.com/uptrace/bun/model_table_slice.go @@ -91,10 +91,31 @@ func (m *sliceTableModel) ScanRows(ctx context.Context, rows *sql.Rows) (int, er return n, nil } +var _ schema.BeforeAppendModelHook = (*sliceTableModel)(nil) + +func (m *sliceTableModel) BeforeAppendModel(ctx context.Context, query Query) error { + if !m.table.HasBeforeAppendModelHook() { + return nil + } + + sliceLen := m.slice.Len() + for i := 0; i < sliceLen; i++ { + strct := m.slice.Index(i) + if !m.sliceOfPtr { + strct = strct.Addr() + } + err := strct.Interface().(schema.BeforeAppendModelHook).BeforeAppendModel(ctx, query) + if err != nil { + return err + } + } + return nil +} + // Inherit these hooks from structTableModel. var ( - _ schema.BeforeScanHook = (*sliceTableModel)(nil) - _ schema.AfterScanHook = (*sliceTableModel)(nil) + _ schema.BeforeScanRowHook = (*sliceTableModel)(nil) + _ schema.AfterScanRowHook = (*sliceTableModel)(nil) ) func (m *sliceTableModel) updateSoftDeleteField(tm time.Time) error { diff --git a/vendor/github.com/uptrace/bun/model_table_struct.go b/vendor/github.com/uptrace/bun/model_table_struct.go index fba17f42a..fadc9284c 100644 --- a/vendor/github.com/uptrace/bun/model_table_struct.go +++ b/vendor/github.com/uptrace/bun/model_table_struct.go @@ -100,38 +100,65 @@ func (m *structTableModel) mountJoins() { } } -var _ schema.BeforeScanHook = (*structTableModel)(nil) +var _ schema.BeforeAppendModelHook = (*structTableModel)(nil) -func (m *structTableModel) BeforeScan(ctx context.Context) error { - if !m.table.HasBeforeScanHook() { +func (m *structTableModel) BeforeAppendModel(ctx context.Context, query Query) error { + if !m.table.HasBeforeAppendModelHook() || !m.strct.IsValid() { return nil } - return callBeforeScanHook(ctx, m.strct.Addr()) + return m.strct.Addr().Interface().(schema.BeforeAppendModelHook).BeforeAppendModel(ctx, query) } -var _ schema.AfterScanHook = (*structTableModel)(nil) +var _ schema.BeforeScanRowHook = (*structTableModel)(nil) -func (m *structTableModel) AfterScan(ctx context.Context) error { - if !m.table.HasAfterScanHook() || !m.structInited { +func (m *structTableModel) BeforeScanRow(ctx context.Context) error { + if m.table.HasBeforeScanRowHook() { + return m.strct.Addr().Interface().(schema.BeforeScanRowHook).BeforeScanRow(ctx) + } + if m.table.HasBeforeScanHook() { + return m.strct.Addr().Interface().(schema.BeforeScanHook).BeforeScan(ctx) + } + return nil +} + +var _ schema.AfterScanRowHook = (*structTableModel)(nil) + +func (m *structTableModel) AfterScanRow(ctx context.Context) error { + if !m.structInited { return nil } - var firstErr error + if m.table.HasAfterScanRowHook() { + firstErr := m.strct.Addr().Interface().(schema.AfterScanRowHook).AfterScanRow(ctx) + + for _, j := range m.joins { + switch j.Relation.Type { + case schema.HasOneRelation, schema.BelongsToRelation: + if err := j.JoinModel.AfterScanRow(ctx); err != nil && firstErr == nil { + firstErr = err + } + } + } - if err := callAfterScanHook(ctx, m.strct.Addr()); err != nil && firstErr == nil { - firstErr = err + return firstErr } - for _, j := range m.joins { - switch j.Relation.Type { - case schema.HasOneRelation, schema.BelongsToRelation: - if err := j.JoinModel.AfterScan(ctx); err != nil && firstErr == nil { - firstErr = err + if m.table.HasAfterScanHook() { + firstErr := m.strct.Addr().Interface().(schema.AfterScanHook).AfterScan(ctx) + + for _, j := range m.joins { + switch j.Relation.Type { + case schema.HasOneRelation, schema.BelongsToRelation: + if err := j.JoinModel.AfterScanRow(ctx); err != nil && firstErr == nil { + firstErr = err + } } } + + return firstErr } - return firstErr + return nil } func (m *structTableModel) getJoin(name string) *relationJoin { @@ -257,7 +284,7 @@ func (m *structTableModel) ScanRow(ctx context.Context, rows *sql.Rows) error { } func (m *structTableModel) scanRow(ctx context.Context, rows *sql.Rows, dest []interface{}) error { - if err := m.BeforeScan(ctx); err != nil { + if err := m.BeforeScanRow(ctx); err != nil { return err } @@ -266,7 +293,7 @@ func (m *structTableModel) scanRow(ctx context.Context, rows *sql.Rows, dest []i return err } - if err := m.AfterScan(ctx); err != nil { + if err := m.AfterScanRow(ctx); err != nil { return err } diff --git a/vendor/github.com/uptrace/bun/package.json b/vendor/github.com/uptrace/bun/package.json index 2dab4c4be..ba6a00007 100644 --- a/vendor/github.com/uptrace/bun/package.json +++ b/vendor/github.com/uptrace/bun/package.json @@ -1,6 +1,6 @@ { "name": "bun", - "version": "1.0.9", + "version": "1.0.14", "main": "index.js", "repository": "git@github.com:uptrace/bun.git", "author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>", diff --git a/vendor/github.com/uptrace/bun/query_base.go b/vendor/github.com/uptrace/bun/query_base.go index 60226890f..9739d93e2 100644 --- a/vendor/github.com/uptrace/bun/query_base.go +++ b/vendor/github.com/uptrace/bun/query_base.go @@ -6,6 +6,7 @@ import ( "database/sql/driver" "errors" "fmt" + "time" "github.com/uptrace/bun/dialect/feature" "github.com/uptrace/bun/internal" @@ -164,6 +165,13 @@ func (q *baseQuery) getModel(dest []interface{}) (Model, error) { return newModel(q.db, dest) } +func (q *baseQuery) beforeAppendModel(ctx context.Context, query Query) error { + if q.tableModel != nil { + return q.tableModel.BeforeAppendModel(ctx, query) + } + return nil +} + //------------------------------------------------------------------------------ func (q *baseQuery) checkSoftDelete() error { @@ -260,6 +268,11 @@ func (q *baseQuery) addColumn(column schema.QueryWithArgs) { } func (q *baseQuery) excludeColumn(columns []string) { + if q.table == nil { + q.setErr(errNilModel) + return + } + if q.columns == nil { for _, f := range q.table.Fields { q.columns = append(q.columns, schema.UnsafeIdent(f.Name)) @@ -456,7 +469,7 @@ func (q *baseQuery) _getFields(omitPK bool) ([]*schema.Field, error) { func (q *baseQuery) scan( ctx context.Context, - iquery IQuery, + iquery Query, query string, model Model, hasDest bool, @@ -488,7 +501,7 @@ func (q *baseQuery) scan( func (q *baseQuery) exec( ctx context.Context, - iquery IQuery, + iquery Query, query string, ) (sql.Result, error) { ctx, event := q.db.beforeQuery(ctx, iquery, query, nil, q.model) @@ -623,11 +636,23 @@ func (q *whereBaseQuery) appendWhere( b = append(b, q.tableModel.Table().SQLAlias...) b = append(b, '.') } - b = append(b, q.tableModel.Table().SoftDeleteField.SQLName...) - if q.flags.Has(deletedFlag) { - b = append(b, " IS NOT NULL"...) + + field := q.tableModel.Table().SoftDeleteField + b = append(b, field.SQLName...) + + if field.NullZero { + if q.flags.Has(deletedFlag) { + b = append(b, " IS NOT NULL"...) + } else { + b = append(b, " IS NULL"...) + } } else { - b = append(b, " IS NULL"...) + if q.flags.Has(deletedFlag) { + b = append(b, " != "...) + } else { + b = append(b, " = "...) + } + b = fmter.Dialect().AppendTime(b, time.Time{}) } } @@ -794,9 +819,11 @@ func (q *returningQuery) addReturningField(field *schema.Field) { func (q *returningQuery) hasReturning() bool { if len(q.returning) == 1 { - switch q.returning[0].Query { - case "null", "NULL": - return false + if ret := q.returning[0]; len(ret.Args) == 0 { + switch ret.Query { + case "", "null", "NULL": + return false + } } } return len(q.returning) > 0 || len(q.returningFields) > 0 diff --git a/vendor/github.com/uptrace/bun/query_delete.go b/vendor/github.com/uptrace/bun/query_delete.go index ef42e644e..a8e14f896 100644 --- a/vendor/github.com/uptrace/bun/query_delete.go +++ b/vendor/github.com/uptrace/bun/query_delete.go @@ -134,9 +134,6 @@ func (q *DeleteQuery) Operation() string { } func (q *DeleteQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) { - if q.err != nil { - return nil, q.err - } fmter = formatterWithModel(fmter, q) if q.isSoftDelete() { @@ -209,19 +206,27 @@ func (q *DeleteQuery) softDeleteSet(fmter schema.Formatter, tm time.Time) string } b = append(b, q.table.SoftDeleteField.SQLName...) b = append(b, " = "...) - b = q.db.Dialect().Append(fmter, b, tm) + b = schema.Append(fmter, b, tm) return internal.String(b) } //------------------------------------------------------------------------------ func (q *DeleteQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result, error) { + if q.err != nil { + return nil, q.err + } + if q.table != nil { if err := q.beforeDeleteHook(ctx); err != nil { return nil, err } } + if err := q.beforeAppendModel(ctx, q); err != nil { + return nil, err + } + queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes()) if err != nil { return nil, err diff --git a/vendor/github.com/uptrace/bun/query_insert.go b/vendor/github.com/uptrace/bun/query_insert.go index e56089d24..42ee49962 100644 --- a/vendor/github.com/uptrace/bun/query_insert.go +++ b/vendor/github.com/uptrace/bun/query_insert.go @@ -84,6 +84,11 @@ func (q *InsertQuery) Column(columns ...string) *InsertQuery { return q } +func (q *InsertQuery) ColumnExpr(query string, args ...interface{}) *InsertQuery { + q.addColumn(schema.SafeQuery(query, args)) + return q +} + func (q *InsertQuery) ExcludeColumn(columns ...string) *InsertQuery { q.excludeColumn(columns) return q @@ -113,7 +118,7 @@ func (q *InsertQuery) WhereOr(query string, args ...interface{}) *InsertQuery { // Returning adds a RETURNING clause to the query. // -// To suppress the auto-generated RETURNING clause, use `Returning("NULL")`. +// To suppress the auto-generated RETURNING clause, use `Returning("")`. func (q *InsertQuery) Returning(query string, args ...interface{}) *InsertQuery { q.addReturning(schema.SafeQuery(query, args)) return q @@ -147,9 +152,6 @@ func (q *InsertQuery) Operation() string { } func (q *InsertQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) { - if q.err != nil { - return nil, q.err - } fmter = formatterWithModel(fmter, q) b, err = q.appendWith(fmter, b) @@ -209,7 +211,18 @@ func (q *InsertQuery) appendColumnsValues( b = append(b, ")"...) } - b = append(b, " SELECT * FROM "...) + b = append(b, " SELECT "...) + + if q.columns != nil { + b, err = q.appendColumns(fmter, b) + if err != nil { + return nil, err + } + } else { + b = append(b, "*"...) + } + + b = append(b, " FROM "...) b, err = q.appendOtherTables(fmter, b) if err != nil { return nil, err @@ -429,6 +442,17 @@ func (q *InsertQuery) appendOn(fmter schema.Formatter, b []byte) (_ []byte, err } b = q.appendSetExcluded(b, fields) + } else if q.onDuplicateKeyUpdate() { + fields, err := q.getDataFields() + if err != nil { + return nil, err + } + + if len(fields) == 0 { + fields = q.tableModel.Table().DataFields + } + + b = q.appendSetValues(b, fields) } if len(q.where) > 0 { @@ -447,6 +471,10 @@ func (q *InsertQuery) onConflictDoUpdate() bool { return strings.HasSuffix(strings.ToUpper(q.on.Query), " DO UPDATE") } +func (q *InsertQuery) onDuplicateKeyUpdate() bool { + return strings.ToUpper(q.on.Query) == "DUPLICATE KEY UPDATE" +} + func (q *InsertQuery) appendSetExcluded(b []byte, fields []*schema.Field) []byte { b = append(b, " SET "...) for i, f := range fields { @@ -460,6 +488,20 @@ func (q *InsertQuery) appendSetExcluded(b []byte, fields []*schema.Field) []byte return b } +func (q *InsertQuery) appendSetValues(b []byte, fields []*schema.Field) []byte { + b = append(b, " "...) + for i, f := range fields { + if i > 0 { + b = append(b, ", "...) + } + b = append(b, f.SQLName...) + b = append(b, " = VALUES("...) + b = append(b, f.SQLName...) + b = append(b, ")"...) + } + return b +} + //------------------------------------------------------------------------------ func (q *InsertQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result, error) { @@ -469,6 +511,13 @@ func (q *InsertQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result } } + if q.err != nil { + return nil, q.err + } + if err := q.beforeAppendModel(ctx, q); err != nil { + return nil, err + } + queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes()) if err != nil { return nil, err diff --git a/vendor/github.com/uptrace/bun/query_select.go b/vendor/github.com/uptrace/bun/query_select.go index 806755cc4..399e3eb0f 100644 --- a/vendor/github.com/uptrace/bun/query_select.go +++ b/vendor/github.com/uptrace/bun/query_select.go @@ -310,14 +310,14 @@ func (q *SelectQuery) Relation(name string, apply ...func(*SelectQuery) *SelectQ return q } -func (q *SelectQuery) forEachHasOneJoin(fn func(*relationJoin) error) error { +func (q *SelectQuery) forEachInlineRelJoin(fn func(*relationJoin) error) error { if q.tableModel == nil { return nil } - return q._forEachHasOneJoin(fn, q.tableModel.getJoins()) + return q._forEachInlineRelJoin(fn, q.tableModel.getJoins()) } -func (q *SelectQuery) _forEachHasOneJoin(fn func(*relationJoin) error, joins []relationJoin) error { +func (q *SelectQuery) _forEachInlineRelJoin(fn func(*relationJoin) error, joins []relationJoin) error { for i := range joins { j := &joins[i] switch j.Relation.Type { @@ -325,7 +325,7 @@ func (q *SelectQuery) _forEachHasOneJoin(fn func(*relationJoin) error, joins []r if err := fn(j); err != nil { return err } - if err := q._forEachHasOneJoin(fn, j.JoinModel.getJoins()); err != nil { + if err := q._forEachInlineRelJoin(fn, j.JoinModel.getJoins()); err != nil { return err } } @@ -370,9 +370,6 @@ func (q *SelectQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, e func (q *SelectQuery) appendQuery( fmter schema.Formatter, b []byte, count bool, ) (_ []byte, err error) { - if q.err != nil { - return nil, q.err - } fmter = formatterWithModel(fmter, q) cteCount := count && (len(q.group) > 0 || q.distinctOn != nil) @@ -423,7 +420,7 @@ func (q *SelectQuery) appendQuery( } } - if err := q.forEachHasOneJoin(func(j *relationJoin) error { + if err := q.forEachInlineRelJoin(func(j *relationJoin) error { b = append(b, ' ') b, err = j.appendHasOneJoin(fmter, b, q) return err @@ -553,13 +550,13 @@ func (q *SelectQuery) appendColumns(fmter schema.Formatter, b []byte) (_ []byte, b = append(b, '*') } - if err := q.forEachHasOneJoin(func(join *relationJoin) error { + if err := q.forEachInlineRelJoin(func(join *relationJoin) error { if len(b) != start { b = append(b, ", "...) start = len(b) } - b, err = q.appendHasOneColumns(fmter, b, join) + b, err = q.appendInlineRelColumns(fmter, b, join) if err != nil { return err } @@ -574,7 +571,7 @@ func (q *SelectQuery) appendColumns(fmter schema.Formatter, b []byte) (_ []byte, return b, nil } -func (q *SelectQuery) appendHasOneColumns( +func (q *SelectQuery) appendInlineRelColumns( fmter schema.Formatter, b []byte, join *relationJoin, ) (_ []byte, err error) { join.applyTo(q) @@ -645,6 +642,14 @@ func (q *SelectQuery) appendOrder(fmter schema.Formatter, b []byte) (_ []byte, e //------------------------------------------------------------------------------ func (q *SelectQuery) Rows(ctx context.Context) (*sql.Rows, error) { + if q.err != nil { + return nil, q.err + } + + if err := q.beforeAppendModel(ctx, q); err != nil { + return nil, err + } + queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes()) if err != nil { return nil, err @@ -655,6 +660,13 @@ func (q *SelectQuery) Rows(ctx context.Context) (*sql.Rows, error) { } func (q *SelectQuery) Exec(ctx context.Context) (res sql.Result, err error) { + if q.err != nil { + return nil, q.err + } + if err := q.beforeAppendModel(ctx, q); err != nil { + return nil, err + } + queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes()) if err != nil { return nil, err @@ -671,6 +683,10 @@ func (q *SelectQuery) Exec(ctx context.Context) (res sql.Result, err error) { } func (q *SelectQuery) Scan(ctx context.Context, dest ...interface{}) error { + if q.err != nil { + return q.err + } + model, err := q.getModel(dest) if err != nil { return err @@ -688,6 +704,10 @@ func (q *SelectQuery) Scan(ctx context.Context, dest ...interface{}) error { } } + if err := q.beforeAppendModel(ctx, q); err != nil { + return err + } + queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes()) if err != nil { return err @@ -736,6 +756,10 @@ func (q *SelectQuery) afterSelectHook(ctx context.Context) error { } func (q *SelectQuery) Count(ctx context.Context) (int, error) { + if q.err != nil { + return 0, q.err + } + qq := countQuery{q} queryBytes, err := qq.AppendQuery(q.db.fmter, nil) @@ -795,6 +819,10 @@ func (q *SelectQuery) ScanAndCount(ctx context.Context, dest ...interface{}) (in } func (q *SelectQuery) Exists(ctx context.Context) (bool, error) { + if q.err != nil { + return false, q.err + } + qq := existsQuery{q} queryBytes, err := qq.AppendQuery(q.db.fmter, nil) @@ -854,6 +882,12 @@ type countQuery struct { } func (q countQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) { + if q.err != nil { + return nil, q.err + } + // if err := q.beforeAppendModel(q); err != nil { + // return nil, err + // } return q.appendQuery(fmter, b, true) } @@ -864,6 +898,13 @@ type existsQuery struct { } func (q existsQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) { + if q.err != nil { + return nil, q.err + } + // if err := q.beforeAppendModel(q); err != nil { + // return nil, err + // } + b = append(b, "SELECT EXISTS ("...) b, err = q.appendQuery(fmter, b, false) diff --git a/vendor/github.com/uptrace/bun/query_update.go b/vendor/github.com/uptrace/bun/query_update.go index a5d9a17f2..df583db25 100644 --- a/vendor/github.com/uptrace/bun/query_update.go +++ b/vendor/github.com/uptrace/bun/query_update.go @@ -100,6 +100,11 @@ func (q *UpdateQuery) Value(column string, expr string, args ...interface{}) *Up return q } +func (q *UpdateQuery) OmitZero() *UpdateQuery { + q.omitZero = true + return q +} + //------------------------------------------------------------------------------ func (q *UpdateQuery) WherePK() *UpdateQuery { @@ -165,9 +170,6 @@ func (q *UpdateQuery) Operation() string { } func (q *UpdateQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) { - if q.err != nil { - return nil, q.err - } fmter = formatterWithModel(fmter, q) b, err = q.appendWith(fmter, b) @@ -254,7 +256,7 @@ func (q *UpdateQuery) appendSetStruct( isTemplate := fmter.IsNop() pos := len(b) for _, f := range fields { - if q.omitZero && f.NullZero && f.HasZeroValue(model.strct) { + if q.omitZero && f.HasZeroValue(model.strct) { continue } @@ -381,12 +383,20 @@ func (db *UpdateQuery) updateSliceWhere(model *sliceTableModel) string { //------------------------------------------------------------------------------ func (q *UpdateQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result, error) { + if q.err != nil { + return nil, q.err + } + if q.table != nil { if err := q.beforeUpdateHook(ctx); err != nil { return nil, err } } + if err := q.beforeAppendModel(ctx, q); err != nil { + return nil, err + } + queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes()) if err != nil { return nil, err diff --git a/vendor/github.com/uptrace/bun/join.go b/vendor/github.com/uptrace/bun/relation_join.go index 7d5ce06fc..e8074e0c6 100644 --- a/vendor/github.com/uptrace/bun/join.go +++ b/vendor/github.com/uptrace/bun/relation_join.go @@ -89,27 +89,33 @@ func (j *relationJoin) manyQuery(q *SelectQuery) *SelectQuery { } func (j *relationJoin) hasManyColumns(q *SelectQuery) *SelectQuery { - if j.Relation.M2MTable != nil { - q = q.ColumnExpr(string(j.Relation.M2MTable.SQLAlias) + ".*") - } - b := make([]byte, 0, 32) + joinTable := j.JoinModel.Table() if len(j.columns) > 0 { for i, col := range j.columns { if i > 0 { b = append(b, ", "...) } + if col.Args == nil { + if field, ok := joinTable.FieldMap[col.Query]; ok { + b = append(b, joinTable.SQLAlias...) + b = append(b, '.') + b = append(b, field.SQLName...) + continue + } + } + var err error b, err = col.AppendQuery(q.db.fmter, b) if err != nil { - q.err = err + q.setErr(err) return q } + } } else { - joinTable := j.JoinModel.Table() b = appendColumns(b, joinTable.SQLAlias, joinTable.Fields) } @@ -138,6 +144,10 @@ func (j *relationJoin) m2mQuery(q *SelectQuery) *SelectQuery { index := j.JoinModel.parentIndex() baseTable := j.BaseModel.Table() + if j.Relation.M2MTable != nil { + q = q.ColumnExpr(string(j.Relation.M2MTable.SQLAlias) + ".*") + } + //nolint var join []byte join = append(join, "JOIN "...) diff --git a/vendor/github.com/uptrace/bun/schema/append.go b/vendor/github.com/uptrace/bun/schema/append.go index 57d292bfe..fccdd17e7 100644 --- a/vendor/github.com/uptrace/bun/schema/append.go +++ b/vendor/github.com/uptrace/bun/schema/append.go @@ -5,13 +5,10 @@ import ( "strconv" "time" - "github.com/vmihailenco/msgpack/v5" - "github.com/uptrace/bun/dialect" - "github.com/uptrace/bun/internal" ) -func Append(fmter Formatter, b []byte, v interface{}, custom CustomAppender) []byte { +func Append(fmter Formatter, b []byte, v interface{}) []byte { switch v := v.(type) { case nil: return dialect.AppendNull(b) @@ -24,11 +21,11 @@ func Append(fmter Formatter, b []byte, v interface{}, custom CustomAppender) []b case int64: return strconv.AppendInt(b, v, 10) case uint: - return strconv.AppendUint(b, uint64(v), 10) + return strconv.AppendInt(b, int64(v), 10) case uint32: - return strconv.AppendUint(b, uint64(v), 10) + return fmter.Dialect().AppendUint32(b, v) case uint64: - return strconv.AppendUint(b, v, 10) + return fmter.Dialect().AppendUint64(b, v) case float32: return dialect.AppendFloat32(b, v) case float64: @@ -36,9 +33,9 @@ func Append(fmter Formatter, b []byte, v interface{}, custom CustomAppender) []b case string: return dialect.AppendString(b, v) case time.Time: - return dialect.AppendTime(b, v) + return fmter.Dialect().AppendTime(b, v) case []byte: - return dialect.AppendBytes(b, v) + return fmter.Dialect().AppendBytes(b, v) case QueryAppender: return AppendQueryAppender(fmter, b, v) default: @@ -46,33 +43,7 @@ func Append(fmter Formatter, b []byte, v interface{}, custom CustomAppender) []b if vv.Kind() == reflect.Ptr && vv.IsNil() { return dialect.AppendNull(b) } - appender := Appender(vv.Type(), custom) + appender := Appender(fmter.Dialect(), vv.Type()) return appender(fmter, b, vv) } } - -func appendMsgpack(fmter Formatter, b []byte, v reflect.Value) []byte { - hexEnc := internal.NewHexEncoder(b) - - enc := msgpack.GetEncoder() - defer msgpack.PutEncoder(enc) - - enc.Reset(hexEnc) - if err := enc.EncodeValue(v); err != nil { - return dialect.AppendError(b, err) - } - - if err := hexEnc.Close(); err != nil { - return dialect.AppendError(b, err) - } - - return hexEnc.Bytes() -} - -func AppendQueryAppender(fmter Formatter, b []byte, app QueryAppender) []byte { - bb, err := app.AppendQuery(fmter, b) - if err != nil { - return dialect.AppendError(b, err) - } - return bb -} diff --git a/vendor/github.com/uptrace/bun/schema/append_value.go b/vendor/github.com/uptrace/bun/schema/append_value.go index 8fe8a13b2..c93f5b291 100644 --- a/vendor/github.com/uptrace/bun/schema/append_value.go +++ b/vendor/github.com/uptrace/bun/schema/append_value.go @@ -7,12 +7,14 @@ import ( "reflect" "strconv" "strings" + "sync" "time" "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/dialect/sqltype" "github.com/uptrace/bun/extra/bunjson" "github.com/uptrace/bun/internal" + "github.com/vmihailenco/msgpack/v5" ) type ( @@ -30,8 +32,8 @@ var appenders = []AppenderFunc{ reflect.Uint: AppendUintValue, reflect.Uint8: AppendUintValue, reflect.Uint16: AppendUintValue, - reflect.Uint32: AppendUintValue, - reflect.Uint64: AppendUintValue, + reflect.Uint32: appendUint32Value, + reflect.Uint64: appendUint64Value, reflect.Uintptr: nil, reflect.Float32: AppendFloat32Value, reflect.Float64: AppendFloat64Value, @@ -49,6 +51,8 @@ var appenders = []AppenderFunc{ reflect.UnsafePointer: nil, } +var appenderMap sync.Map + func FieldAppender(dialect Dialect, field *Field) AppenderFunc { if field.Tag.HasOption("msgpack") { return appendMsgpack @@ -59,10 +63,23 @@ func FieldAppender(dialect Dialect, field *Field) AppenderFunc { return AppendJSONValue } - return dialect.Appender(field.StructField.Type) + return Appender(dialect, field.StructField.Type) +} + +func Appender(dialect Dialect, typ reflect.Type) AppenderFunc { + if v, ok := appenderMap.Load(typ); ok { + return v.(AppenderFunc) + } + + fn := appender(dialect, typ) + + if v, ok := appenderMap.LoadOrStore(typ, fn); ok { + return v.(AppenderFunc) + } + return fn } -func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc { +func appender(dialect Dialect, typ reflect.Type) AppenderFunc { switch typ { case bytesType: return appendBytesValue @@ -80,7 +97,7 @@ func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc { return appendQueryAppenderValue } if typ.Implements(driverValuerType) { - return driverValueAppender(custom) + return appendDriverValue } kind := typ.Kind() @@ -88,18 +105,18 @@ func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc { if kind != reflect.Ptr { ptr := reflect.PtrTo(typ) if ptr.Implements(queryAppenderType) { - return addrAppender(appendQueryAppenderValue, custom) + return addrAppender(appendQueryAppenderValue) } if ptr.Implements(driverValuerType) { - return addrAppender(driverValueAppender(custom), custom) + return addrAppender(appendDriverValue) } } switch kind { case reflect.Interface: - return ifaceAppenderFunc(typ, custom) + return ifaceAppenderFunc case reflect.Ptr: - if fn := Appender(typ.Elem(), custom); fn != nil { + if fn := Appender(dialect, typ.Elem()); fn != nil { return PtrAppender(fn) } case reflect.Slice: @@ -112,23 +129,16 @@ func Appender(typ reflect.Type, custom CustomAppender) AppenderFunc { } } - if custom != nil { - if fn := custom(typ); fn != nil { - return fn - } - } return appenders[typ.Kind()] } -func ifaceAppenderFunc(typ reflect.Type, custom func(reflect.Type) AppenderFunc) AppenderFunc { - return func(fmter Formatter, b []byte, v reflect.Value) []byte { - if v.IsNil() { - return dialect.AppendNull(b) - } - elem := v.Elem() - appender := Appender(elem.Type(), custom) - return appender(fmter, b, elem) +func ifaceAppenderFunc(fmter Formatter, b []byte, v reflect.Value) []byte { + if v.IsNil() { + return dialect.AppendNull(b) } + elem := v.Elem() + appender := Appender(fmter.Dialect(), elem.Type()) + return appender(fmter, b, elem) } func PtrAppender(fn AppenderFunc) AppenderFunc { @@ -152,6 +162,14 @@ func AppendUintValue(fmter Formatter, b []byte, v reflect.Value) []byte { return strconv.AppendUint(b, v.Uint(), 10) } +func appendUint32Value(fmter Formatter, b []byte, v reflect.Value) []byte { + return fmter.Dialect().AppendUint32(b, uint32(v.Uint())) +} + +func appendUint64Value(fmter Formatter, b []byte, v reflect.Value) []byte { + return fmter.Dialect().AppendUint64(b, v.Uint()) +} + func AppendFloat32Value(fmter Formatter, b []byte, v reflect.Value) []byte { return dialect.AppendFloat32(b, float32(v.Float())) } @@ -161,17 +179,17 @@ func AppendFloat64Value(fmter Formatter, b []byte, v reflect.Value) []byte { } func appendBytesValue(fmter Formatter, b []byte, v reflect.Value) []byte { - return dialect.AppendBytes(b, v.Bytes()) + return fmter.Dialect().AppendBytes(b, v.Bytes()) } func appendArrayBytesValue(fmter Formatter, b []byte, v reflect.Value) []byte { if v.CanAddr() { - return dialect.AppendBytes(b, v.Slice(0, v.Len()).Bytes()) + return fmter.Dialect().AppendBytes(b, v.Slice(0, v.Len()).Bytes()) } tmp := make([]byte, v.Len()) reflect.Copy(reflect.ValueOf(tmp), v) - b = dialect.AppendBytes(b, tmp) + b = fmter.Dialect().AppendBytes(b, tmp) return b } @@ -189,12 +207,12 @@ func AppendJSONValue(fmter Formatter, b []byte, v reflect.Value) []byte { bb = bb[:len(bb)-1] } - return dialect.AppendJSON(b, bb) + return fmter.Dialect().AppendJSON(b, bb) } func appendTimeValue(fmter Formatter, b []byte, v reflect.Value) []byte { tm := v.Interface().(time.Time) - return dialect.AppendTime(b, tm) + return fmter.Dialect().AppendTime(b, tm) } func appendIPValue(fmter Formatter, b []byte, v reflect.Value) []byte { @@ -219,21 +237,15 @@ func appendQueryAppenderValue(fmter Formatter, b []byte, v reflect.Value) []byte return AppendQueryAppender(fmter, b, v.Interface().(QueryAppender)) } -func driverValueAppender(custom CustomAppender) AppenderFunc { - return func(fmter Formatter, b []byte, v reflect.Value) []byte { - return appendDriverValue(fmter, b, v.Interface().(driver.Valuer), custom) - } -} - -func appendDriverValue(fmter Formatter, b []byte, v driver.Valuer, custom CustomAppender) []byte { - value, err := v.Value() +func appendDriverValue(fmter Formatter, b []byte, v reflect.Value) []byte { + value, err := v.Interface().(driver.Valuer).Value() if err != nil { return dialect.AppendError(b, err) } - return Append(fmter, b, value, custom) + return Append(fmter, b, value) } -func addrAppender(fn AppenderFunc, custom CustomAppender) AppenderFunc { +func addrAppender(fn AppenderFunc) AppenderFunc { return func(fmter Formatter, b []byte, v reflect.Value) []byte { if !v.CanAddr() { err := fmt.Errorf("bun: Append(nonaddressable %T)", v.Interface()) @@ -242,3 +254,29 @@ func addrAppender(fn AppenderFunc, custom CustomAppender) AppenderFunc { return fn(fmter, b, v.Addr()) } } + +func appendMsgpack(fmter Formatter, b []byte, v reflect.Value) []byte { + hexEnc := internal.NewHexEncoder(b) + + enc := msgpack.GetEncoder() + defer msgpack.PutEncoder(enc) + + enc.Reset(hexEnc) + if err := enc.EncodeValue(v); err != nil { + return dialect.AppendError(b, err) + } + + if err := hexEnc.Close(); err != nil { + return dialect.AppendError(b, err) + } + + return hexEnc.Bytes() +} + +func AppendQueryAppender(fmter Formatter, b []byte, app QueryAppender) []byte { + bb, err := app.AppendQuery(fmter, b) + if err != nil { + return dialect.AppendError(b, err) + } + return bb +} diff --git a/vendor/github.com/uptrace/bun/schema/dialect.go b/vendor/github.com/uptrace/bun/schema/dialect.go index c50de715a..f015807dc 100644 --- a/vendor/github.com/uptrace/bun/schema/dialect.go +++ b/vendor/github.com/uptrace/bun/schema/dialect.go @@ -2,11 +2,12 @@ package schema import ( "database/sql" - "reflect" - "sync" + "strconv" + "time" "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/dialect/feature" + "github.com/uptrace/bun/internal/parser" ) type Dialect interface { @@ -19,20 +20,76 @@ type Dialect interface { OnTable(table *Table) IdentQuote() byte - Append(fmter Formatter, b []byte, v interface{}) []byte - Appender(typ reflect.Type) AppenderFunc - FieldAppender(field *Field) AppenderFunc - Scanner(typ reflect.Type) ScannerFunc + + AppendUint32(b []byte, n uint32) []byte + AppendUint64(b []byte, n uint64) []byte + AppendTime(b []byte, tm time.Time) []byte + AppendBytes(b []byte, bs []byte) []byte + AppendJSON(b, jsonb []byte) []byte +} + +//------------------------------------------------------------------------------ + +type BaseDialect struct{} + +func (BaseDialect) AppendUint32(b []byte, n uint32) []byte { + return strconv.AppendUint(b, uint64(n), 10) +} + +func (BaseDialect) AppendUint64(b []byte, n uint64) []byte { + return strconv.AppendUint(b, n, 10) +} + +func (BaseDialect) AppendTime(b []byte, tm time.Time) []byte { + b = append(b, '\'') + b = tm.UTC().AppendFormat(b, "2006-01-02 15:04:05.999999-07:00") + b = append(b, '\'') + return b +} + +func (BaseDialect) AppendBytes(b, bs []byte) []byte { + return dialect.AppendBytes(b, bs) +} + +func (BaseDialect) AppendJSON(b, jsonb []byte) []byte { + b = append(b, '\'') + + p := parser.New(jsonb) + for p.Valid() { + c := p.Read() + switch c { + case '"': + b = append(b, '"') + case '\'': + b = append(b, "''"...) + case '\000': + continue + case '\\': + if p.SkipBytes([]byte("u0000")) { + b = append(b, `\\u0000`...) + } else { + b = append(b, '\\') + if p.Valid() { + b = append(b, p.Read()) + } + } + default: + b = append(b, c) + } + } + + b = append(b, '\'') + + return b } //------------------------------------------------------------------------------ type nopDialect struct { + BaseDialect + tables *Tables features feature.Feature - - appenderMap sync.Map - scannerMap sync.Map } func newNopDialect() *nopDialect { @@ -63,37 +120,3 @@ func (d *nopDialect) OnTable(table *Table) {} func (d *nopDialect) IdentQuote() byte { return '"' } - -func (d *nopDialect) Append(fmter Formatter, b []byte, v interface{}) []byte { - return Append(fmter, b, v, nil) -} - -func (d *nopDialect) Appender(typ reflect.Type) AppenderFunc { - if v, ok := d.appenderMap.Load(typ); ok { - return v.(AppenderFunc) - } - - fn := Appender(typ, nil) - - if v, ok := d.appenderMap.LoadOrStore(typ, fn); ok { - return v.(AppenderFunc) - } - return fn -} - -func (d *nopDialect) FieldAppender(field *Field) AppenderFunc { - return FieldAppender(d, field) -} - -func (d *nopDialect) Scanner(typ reflect.Type) ScannerFunc { - if v, ok := d.scannerMap.Load(typ); ok { - return v.(ScannerFunc) - } - - fn := Scanner(typ) - - if v, ok := d.scannerMap.LoadOrStore(typ, fn); ok { - return v.(ScannerFunc) - } - return fn -} diff --git a/vendor/github.com/uptrace/bun/schema/formatter.go b/vendor/github.com/uptrace/bun/schema/formatter.go index 45a246307..dd1859acf 100644 --- a/vendor/github.com/uptrace/bun/schema/formatter.go +++ b/vendor/github.com/uptrace/bun/schema/formatter.go @@ -50,7 +50,7 @@ func (f Formatter) AppendValue(b []byte, v reflect.Value) []byte { if v.Kind() == reflect.Ptr && v.IsNil() { return dialect.AppendNull(b) } - appender := f.dialect.Appender(v.Type()) + appender := Appender(f.dialect, v.Type()) return appender(f, b, v) } @@ -167,7 +167,7 @@ func (f Formatter) appendArg(b []byte, arg interface{}) []byte { } return bb default: - return f.dialect.Append(f, b, arg) + return Append(f, b, arg) } } diff --git a/vendor/github.com/uptrace/bun/schema/hook.go b/vendor/github.com/uptrace/bun/schema/hook.go index 5391981d5..624601c9f 100644 --- a/vendor/github.com/uptrace/bun/schema/hook.go +++ b/vendor/github.com/uptrace/bun/schema/hook.go @@ -2,9 +2,32 @@ package schema import ( "context" + "database/sql" "reflect" ) +type Model interface { + ScanRows(ctx context.Context, rows *sql.Rows) (int, error) + Value() interface{} +} + +type Query interface { + QueryAppender + Operation() string + GetModel() Model + GetTableName() string +} + +//------------------------------------------------------------------------------ + +type BeforeAppendModelHook interface { + BeforeAppendModel(ctx context.Context, query Query) error +} + +var beforeAppendModelHookType = reflect.TypeOf((*BeforeAppendModelHook)(nil)).Elem() + +//------------------------------------------------------------------------------ + type BeforeScanHook interface { BeforeScan(context.Context) error } @@ -18,3 +41,19 @@ type AfterScanHook interface { } var afterScanHookType = reflect.TypeOf((*AfterScanHook)(nil)).Elem() + +//------------------------------------------------------------------------------ + +type BeforeScanRowHook interface { + BeforeScanRow(context.Context) error +} + +var beforeScanRowHookType = reflect.TypeOf((*BeforeScanRowHook)(nil)).Elem() + +//------------------------------------------------------------------------------ + +type AfterScanRowHook interface { + AfterScanRow(context.Context) error +} + +var afterScanRowHookType = reflect.TypeOf((*AfterScanRowHook)(nil)).Elem() diff --git a/vendor/github.com/uptrace/bun/schema/scan.go b/vendor/github.com/uptrace/bun/schema/scan.go index 60ad27d53..30abcfc35 100644 --- a/vendor/github.com/uptrace/bun/schema/scan.go +++ b/vendor/github.com/uptrace/bun/schema/scan.go @@ -8,6 +8,7 @@ import ( "reflect" "strconv" "strings" + "sync" "time" "github.com/vmihailenco/msgpack/v5" @@ -52,6 +53,8 @@ func init() { } } +var scannerMap sync.Map + func FieldScanner(dialect Dialect, field *Field) ScannerFunc { if field.Tag.HasOption("msgpack") { return scanMsgpack @@ -65,10 +68,23 @@ func FieldScanner(dialect Dialect, field *Field) ScannerFunc { return scanJSONIntoInterface } } - return dialect.Scanner(field.StructField.Type) + return Scanner(field.StructField.Type) } func Scanner(typ reflect.Type) ScannerFunc { + if v, ok := scannerMap.Load(typ); ok { + return v.(ScannerFunc) + } + + fn := scanner(typ) + + if v, ok := scannerMap.LoadOrStore(typ, fn); ok { + return v.(ScannerFunc) + } + return fn +} + +func scanner(typ reflect.Type) ScannerFunc { kind := typ.Kind() if kind == reflect.Ptr { diff --git a/vendor/github.com/uptrace/bun/schema/sqlfmt.go b/vendor/github.com/uptrace/bun/schema/sqlfmt.go index bbdb0a01f..93a801c86 100644 --- a/vendor/github.com/uptrace/bun/schema/sqlfmt.go +++ b/vendor/github.com/uptrace/bun/schema/sqlfmt.go @@ -1,5 +1,11 @@ package schema +import ( + "strings" + + "github.com/uptrace/bun/internal" +) + type QueryAppender interface { AppendQuery(fmter Formatter, b []byte) ([]byte, error) } @@ -42,8 +48,13 @@ var _ QueryAppender = QueryWithArgs{} func SafeQuery(query string, args []interface{}) QueryWithArgs { if args == nil { args = make([]interface{}, 0) + } else if len(query) > 0 && strings.IndexByte(query, '?') == -1 { + internal.Warn.Printf("query %q has args %v, but no placeholders", query, args) + } + return QueryWithArgs{ + Query: query, + Args: args, } - return QueryWithArgs{Query: query, Args: args} } func UnsafeIdent(ident string) QueryWithArgs { diff --git a/vendor/github.com/uptrace/bun/schema/sqltype.go b/vendor/github.com/uptrace/bun/schema/sqltype.go index 72609cf7a..90551d6aa 100644 --- a/vendor/github.com/uptrace/bun/schema/sqltype.go +++ b/vendor/github.com/uptrace/bun/schema/sqltype.go @@ -61,6 +61,14 @@ func DiscoverSQLType(typ reflect.Type) string { case nullStringType: return sqltype.VarChar } + + switch typ.Kind() { + case reflect.Slice: + if typ.Elem().Kind() == reflect.Uint8 { + return sqltype.Blob + } + } + return sqlTypes[typ.Kind()] } @@ -99,7 +107,7 @@ func (tm NullTime) AppendQuery(fmter Formatter, b []byte) ([]byte, error) { if tm.IsZero() { return dialect.AppendNull(b), nil } - return dialect.AppendTime(b, tm.Time), nil + return fmter.Dialect().AppendTime(b, tm.Time), nil } func (tm *NullTime) Scan(src interface{}) error { diff --git a/vendor/github.com/uptrace/bun/schema/table.go b/vendor/github.com/uptrace/bun/schema/table.go index 213f821ab..2d762e135 100644 --- a/vendor/github.com/uptrace/bun/schema/table.go +++ b/vendor/github.com/uptrace/bun/schema/table.go @@ -15,8 +15,11 @@ import ( ) const ( - beforeScanHookFlag internal.Flag = 1 << iota + beforeAppendModelHookFlag internal.Flag = 1 << iota + beforeScanHookFlag afterScanHookFlag + beforeScanRowHookFlag + afterScanRowHookFlag ) var ( @@ -84,8 +87,13 @@ func newTable(dialect Dialect, typ reflect.Type) *Table { typ reflect.Type flag internal.Flag }{ + {beforeAppendModelHookType, beforeAppendModelHookFlag}, + {beforeScanHookType, beforeScanHookFlag}, {afterScanHookType, afterScanHookFlag}, + + {beforeScanRowHookType, beforeScanRowHookFlag}, + {afterScanRowHookType, afterScanRowHookFlag}, } typ = reflect.PtrTo(t.Type) @@ -95,6 +103,22 @@ func newTable(dialect Dialect, typ reflect.Type) *Table { } } + // Deprecated. + deprecatedHooks := []struct { + typ reflect.Type + flag internal.Flag + msg string + }{ + {beforeScanHookType, beforeScanHookFlag, "rename BeforeScan hook to BeforeScanRow"}, + {afterScanHookType, afterScanHookFlag, "rename AfterScan hook to AfterScanRow"}, + } + for _, hook := range deprecatedHooks { + if typ.Implements(hook.typ) { + internal.Deprecated.Printf("%s: %s", t.TypeName, hook.msg) + t.flags = t.flags.Set(hook.flag) + } + } + return t } @@ -334,15 +358,6 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field { if tag.HasOption("pk") { field.markAsPK() } - if tag.HasOption("allowzero") { - if tag.HasOption("nullzero") { - internal.Warn.Printf( - "%s.%s: nullzero and allowzero options are mutually exclusive", - t.TypeName, f.Name, - ) - } - field.NullZero = false - } if v, ok := tag.Options["unique"]; ok { // Split the value by comma, this will allow multiple names to be specified. @@ -362,7 +377,7 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field { field.UserSQLType = s } field.DiscoveredSQLType = DiscoverSQLType(field.IndirectType) - field.Append = t.dialect.FieldAppender(field) + field.Append = FieldAppender(t.dialect, field) field.Scan = FieldScanner(t.dialect, field) field.IsZero = zeroChecker(field.StructField.Type) @@ -385,6 +400,17 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field { t.UpdateSoftDeleteField = softDeleteFieldUpdater(field) } + // Check this in the end to undo NullZero. + if tag.HasOption("allowzero") { + if tag.HasOption("nullzero") { + internal.Warn.Printf( + "%s.%s: nullzero and allowzero options are mutually exclusive", + t.TypeName, f.Name, + ) + } + field.NullZero = false + } + return field } @@ -775,9 +801,18 @@ func (t *Table) inlineFields(field *Field, seen map[reflect.Type]struct{}) { //------------------------------------------------------------------------------ -func (t *Table) Dialect() Dialect { return t.dialect } +func (t *Table) Dialect() Dialect { return t.dialect } + +func (t *Table) HasBeforeAppendModelHook() bool { return t.flags.Has(beforeAppendModelHookFlag) } + +// DEPRECATED. Use HasBeforeScanRowHook. func (t *Table) HasBeforeScanHook() bool { return t.flags.Has(beforeScanHookFlag) } -func (t *Table) HasAfterScanHook() bool { return t.flags.Has(afterScanHookFlag) } + +// DEPRECATED. Use HasAfterScanRowHook. +func (t *Table) HasAfterScanHook() bool { return t.flags.Has(afterScanHookFlag) } + +func (t *Table) HasBeforeScanRowHook() bool { return t.flags.Has(beforeScanRowHookFlag) } +func (t *Table) HasAfterScanRowHook() bool { return t.flags.Has(afterScanRowHookFlag) } //------------------------------------------------------------------------------ diff --git a/vendor/github.com/uptrace/bun/version.go b/vendor/github.com/uptrace/bun/version.go index 9e4962e2c..f13205b85 100644 --- a/vendor/github.com/uptrace/bun/version.go +++ b/vendor/github.com/uptrace/bun/version.go @@ -2,5 +2,5 @@ package bun // Version is the current release version. func Version() string { - return "1.0.9" + return "1.0.14" } |