diff options
Diffstat (limited to 'vendor/github.com/uptrace')
20 files changed, 344 insertions, 172 deletions
diff --git a/vendor/github.com/uptrace/bun/CHANGELOG.md b/vendor/github.com/uptrace/bun/CHANGELOG.md index 5e738f2ea..f644ed6f5 100644 --- a/vendor/github.com/uptrace/bun/CHANGELOG.md +++ b/vendor/github.com/uptrace/bun/CHANGELOG.md @@ -1,3 +1,45 @@ +## [1.0.17](https://github.com/uptrace/bun/compare/v1.0.16...v1.0.17) (2021-11-11) + + +### Bug Fixes + +* don't call rollback when tx is already done ([8246c2a](https://github.com/uptrace/bun/commit/8246c2a63e2e6eba314201c6ba87f094edf098b9)) +* **mysql:** escape backslash char in strings ([fb32029](https://github.com/uptrace/bun/commit/fb32029ea7604d066800b16df21f239b71bf121d)) + + + +## [1.0.16](https://github.com/uptrace/bun/compare/v1.0.15...v1.0.16) (2021-11-07) + + +### Bug Fixes + +* call query hook when tx is started, committed, or rolled back ([30e85b5](https://github.com/uptrace/bun/commit/30e85b5366b2e51951ef17a0cf362b58f708dab1)) +* **pgdialect:** auto-enable array support if the sql type is an array ([62c1012](https://github.com/uptrace/bun/commit/62c1012b2482e83969e5c6f5faf89e655ce78138)) + + +### Features + +* support multiple tag options join:left_col1=right_col1,join:left_col2=right_col2 ([78cd5aa](https://github.com/uptrace/bun/commit/78cd5aa60a5c7d1323bb89081db2b2b811113052)) +* **tag:** log with bad tag name ([4e82d75](https://github.com/uptrace/bun/commit/4e82d75be2dabdba1a510df4e1fbb86092f92f4c)) + + + +## [1.0.15](https://github.com/uptrace/bun/compare/v1.0.14...v1.0.15) (2021-10-29) + + +### Bug Fixes + +* fixed bug creating table when model has no columns ([042c50b](https://github.com/uptrace/bun/commit/042c50bfe41caaa6e279e02c887c3a84a3acd84f)) +* init table with dialect once ([9a1ce1e](https://github.com/uptrace/bun/commit/9a1ce1e492602742bb2f587e9ed24e50d7d07cad)) + + +### Features + +* accept columns in WherePK ([b3e7035](https://github.com/uptrace/bun/commit/b3e70356db1aa4891115a10902316090fccbc8bf)) +* support ADD COLUMN IF NOT EXISTS ([ca7357c](https://github.com/uptrace/bun/commit/ca7357cdfe283e2f0b94eb638372e18401c486e9)) + + + ## [1.0.14](https://github.com/uptrace/bun/compare/v1.0.13...v1.0.14) (2021-10-24) diff --git a/vendor/github.com/uptrace/bun/README.md b/vendor/github.com/uptrace/bun/README.md index 9a8ed46c2..30ab3a2aa 100644 --- a/vendor/github.com/uptrace/bun/README.md +++ b/vendor/github.com/uptrace/bun/README.md @@ -30,8 +30,7 @@ Main features are: Resources: -- To ask questions, join [Discord](https://discord.gg/rWtp5Aj) or use - [Discussions](https://github.com/uptrace/bun/discussions). +- [Discussions](https://github.com/uptrace/bun/discussions). - [Newsletter](https://blog.uptrace.dev/pages/newsletter.html) to get latest updates. - [Examples](https://github.com/uptrace/bun/tree/master/example) - [Documentation](https://bun.uptrace.dev/) @@ -41,6 +40,7 @@ Resources: Projects using Bun: - [gotosocial](https://github.com/superseriousbusiness/gotosocial) - Golang fediverse server. +- [input-output-hk/cicero](https://github.com/input-output-hk/cicero) - [RealWorld app](https://github.com/go-bun/bun-realworld-app) <details> @@ -95,6 +95,55 @@ Projects using Bun: </details> +## Why another database client? + +So you can elegantly write complex queries: + +```go +regionalSales := db.NewSelect(). + ColumnExpr("region"). + ColumnExpr("SUM(amount) AS total_sales"). + TableExpr("orders"). + GroupExpr("region") + +topRegions := db.NewSelect(). + ColumnExpr("region"). + TableExpr("regional_sales"). + Where("total_sales > (SELECT SUM(total_sales) / 10 FROM regional_sales)") + +err := db.NewSelect(). + With("regional_sales", regionalSales). + With("top_regions", topRegions). + ColumnExpr("region"). + ColumnExpr("product"). + ColumnExpr("SUM(quantity) AS product_units"). + ColumnExpr("SUM(amount) AS product_sales"). + TableExpr("orders"). + Where("region IN (SELECT region FROM top_regions)"). + GroupExpr("region"). + GroupExpr("product"). + Scan(ctx) +``` + +```sql +WITH regional_sales AS ( + SELECT region, SUM(amount) AS total_sales + FROM orders + GROUP BY region +), top_regions AS ( + SELECT region + FROM regional_sales + WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) +) +SELECT region, + product, + SUM(quantity) AS product_units, + SUM(amount) AS product_sales +FROM orders +WHERE region IN (SELECT region FROM top_regions) +GROUP BY region, product +``` + ## Installation ```go @@ -149,30 +198,6 @@ err := db.NewSelect(). Scan(ctx) ``` -The code above is equivalent to: - -```go -query := "SELECT id, name FROM users AS user WHERE name != '' ORDER BY id ASC LIMIT 1" - -rows, err := sqldb.QueryContext(ctx, query) -if err != nil { - panic(err) -} - -if !rows.Next() { - panic(sql.ErrNoRows) -} - -user := new(User) -if err := db.ScanRow(ctx, rows, user); err != nil { - panic(err) -} - -if err := rows.Err(); err != nil { - panic(err) -} -``` - ## Basic example To provide initial data for our [example](/example/basic/), we will use Bun diff --git a/vendor/github.com/uptrace/bun/db.go b/vendor/github.com/uptrace/bun/db.go index 72fe118a9..d42669493 100644 --- a/vendor/github.com/uptrace/bun/db.go +++ b/vendor/github.com/uptrace/bun/db.go @@ -356,7 +356,8 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (Stmt, error) { //------------------------------------------------------------------------------ type Tx struct { - db *DB + ctx context.Context + db *DB *sql.Tx } @@ -369,11 +370,20 @@ func (db *DB) RunInTx( if err != nil { return err } - defer tx.Rollback() //nolint:errcheck + + var done bool + + defer func() { + if !done { + _ = tx.Rollback() + } + }() if err := fn(ctx, tx); err != nil { return err } + + done = true return tx.Commit() } @@ -382,16 +392,33 @@ func (db *DB) Begin() (Tx, error) { } func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (Tx, error) { + ctx, event := db.beforeQuery(ctx, nil, "BEGIN", nil, nil) tx, err := db.DB.BeginTx(ctx, opts) + db.afterQuery(ctx, event, nil, err) if err != nil { return Tx{}, err } return Tx{ - db: db, - Tx: tx, + ctx: ctx, + db: db, + Tx: tx, }, nil } +func (tx Tx) Commit() error { + ctx, event := tx.db.beforeQuery(tx.ctx, nil, "COMMIT", nil, nil) + err := tx.Tx.Commit() + tx.db.afterQuery(ctx, event, nil, err) + return err +} + +func (tx Tx) Rollback() error { + ctx, event := tx.db.beforeQuery(tx.ctx, nil, "ROLLBACK", nil, nil) + err := tx.Tx.Rollback() + tx.db.afterQuery(ctx, event, nil, err) + return err +} + func (tx Tx) Exec(query string, args ...interface{}) (sql.Result, error) { return tx.ExecContext(context.TODO(), query, args...) } diff --git a/vendor/github.com/uptrace/bun/dialect/append.go b/vendor/github.com/uptrace/bun/dialect/append.go index c9d137946..0a25ee22d 100644 --- a/vendor/github.com/uptrace/bun/dialect/append.go +++ b/vendor/github.com/uptrace/bun/dialect/append.go @@ -1,10 +1,8 @@ package dialect import ( - "encoding/hex" "math" "strconv" - "unicode/utf8" "github.com/uptrace/bun/internal" ) @@ -48,50 +46,6 @@ func appendFloat(b []byte, v float64, bitSize int) []byte { } } -func AppendString(b []byte, s string) []byte { - b = append(b, '\'') - for _, r := range s { - if r == '\000' { - continue - } - - if r == '\'' { - b = append(b, '\'', '\'') - continue - } - - if r < utf8.RuneSelf { - b = append(b, byte(r)) - continue - } - - l := len(b) - if cap(b)-l < utf8.UTFMax { - b = append(b, make([]byte, utf8.UTFMax)...) - } - n := utf8.EncodeRune(b[l:l+utf8.UTFMax], r) - b = b[:l+n] - } - b = append(b, '\'') - return b -} - -func 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(bs)))...) - hex.Encode(b[s:], bs) - - b = append(b, '\'') - - return b -} - //------------------------------------------------------------------------------ func AppendIdent(b []byte, field string, quote byte) []byte { diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go index bac38972f..aba82eac1 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/dialect.go @@ -3,6 +3,7 @@ package pgdialect import ( "database/sql" "strconv" + "strings" "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/dialect/feature" @@ -68,7 +69,7 @@ func (d *Dialect) onField(field *schema.Field) { } } - if field.Tag.HasOption("array") { + if field.Tag.HasOption("array") || strings.HasSuffix(field.UserSQLType, "[]") { field.Append = d.arrayAppender(field.StructField.Type) field.Scan = arrayScanner(field.StructField.Type) } diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go index dab0446ed..1fbfa7d7f 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/sqltype.go @@ -4,7 +4,6 @@ import ( "encoding/json" "net" "reflect" - "time" "github.com/uptrace/bun/dialect/sqltype" "github.com/uptrace/bun/schema" @@ -41,7 +40,6 @@ const ( ) var ( - timeType = reflect.TypeOf((*time.Time)(nil)).Elem() ipType = reflect.TypeOf((*net.IP)(nil)).Elem() ipNetType = reflect.TypeOf((*net.IPNet)(nil)).Elem() jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem() @@ -52,11 +50,11 @@ func fieldSQLType(field *schema.Field) string { return field.UserSQLType } - if v, ok := field.Tag.Options["composite"]; ok { + if v, ok := field.Tag.Option("composite"); ok { return v } - if _, ok := field.Tag.Options["hstore"]; ok { + if _, ok := field.Tag.Option("hstore"); ok { return "hstore" } diff --git a/vendor/github.com/uptrace/bun/internal/tagparser/parser.go b/vendor/github.com/uptrace/bun/internal/tagparser/parser.go index eb3246536..a3905853d 100644 --- a/vendor/github.com/uptrace/bun/internal/tagparser/parser.go +++ b/vendor/github.com/uptrace/bun/internal/tagparser/parser.go @@ -6,7 +6,11 @@ import ( type Tag struct { Name string - Options map[string]string + Options map[string][]string +} + +func (t Tag) IsZero() bool { + return t.Name == "" && t.Options == nil } func (t Tag) HasOption(name string) bool { @@ -14,7 +18,17 @@ func (t Tag) HasOption(name string) bool { return ok } +func (t Tag) Option(name string) (string, bool) { + if vs, ok := t.Options[name]; ok { + return vs[len(vs)-1], true + } + return "", false +} + func Parse(s string) Tag { + if s == "" { + return Tag{} + } p := parser{ s: s, } @@ -45,9 +59,13 @@ func (p *parser) addOption(key, value string) { return } if p.tag.Options == nil { - p.tag.Options = make(map[string]string) + p.tag.Options = make(map[string][]string) + } + if vs, ok := p.tag.Options[key]; ok { + p.tag.Options[key] = append(vs, value) + } else { + p.tag.Options[key] = []string{value} } - p.tag.Options[key] = value } func (p *parser) parse() { diff --git a/vendor/github.com/uptrace/bun/package.json b/vendor/github.com/uptrace/bun/package.json index ba6a00007..f088afd3a 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.14", + "version": "1.0.17", "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 9739d93e2..4cf31d04e 100644 --- a/vendor/github.com/uptrace/bun/query_base.go +++ b/vendor/github.com/uptrace/bun/query_base.go @@ -14,8 +14,7 @@ import ( ) const ( - wherePKFlag internal.Flag = 1 << iota - forceDeleteFlag + forceDeleteFlag internal.Flag = 1 << iota deletedFlag allWithDeletedFlag ) @@ -580,7 +579,8 @@ func formatterWithModel(fmter schema.Formatter, model schema.NamedArgAppender) s type whereBaseQuery struct { baseQuery - where []schema.QueryWithSep + where []schema.QueryWithSep + whereFields []*schema.Field } func (q *whereBaseQuery) addWhere(where schema.QueryWithSep) { @@ -601,10 +601,46 @@ func (q *whereBaseQuery) addWhereGroup(sep string, where []schema.QueryWithSep) q.addWhere(schema.SafeQueryWithSep("", nil, ")")) } +func (q *whereBaseQuery) addWhereCols(cols []string) { + if q.table == nil { + err := fmt.Errorf("bun: got %T, but WherePK requires a struct or slice-based model", q.model) + q.setErr(err) + return + } + + var fields []*schema.Field + + if cols == nil { + if err := q.table.CheckPKs(); err != nil { + q.setErr(err) + return + } + fields = q.table.PKs + } else { + fields = make([]*schema.Field, len(cols)) + for i, col := range cols { + field, err := q.table.Field(col) + if err != nil { + q.setErr(err) + return + } + fields[i] = field + } + } + + if q.whereFields != nil { + err := errors.New("bun: WherePK can only be called once") + q.setErr(err) + return + } + + q.whereFields = fields +} + func (q *whereBaseQuery) mustAppendWhere( fmter schema.Formatter, b []byte, withAlias bool, ) ([]byte, error) { - if len(q.where) == 0 && !q.flags.Has(wherePKFlag) { + if len(q.where) == 0 && q.whereFields == nil { err := errors.New("bun: Update and Delete queries require at least one Where") return nil, err } @@ -614,7 +650,7 @@ func (q *whereBaseQuery) mustAppendWhere( func (q *whereBaseQuery) appendWhere( fmter schema.Formatter, b []byte, withAlias bool, ) (_ []byte, err error) { - if len(q.where) == 0 && !q.isSoftDelete() && !q.flags.Has(wherePKFlag) { + if len(q.where) == 0 && q.whereFields == nil && !q.isSoftDelete() { return b, nil } @@ -656,11 +692,11 @@ func (q *whereBaseQuery) appendWhere( } } - if q.flags.Has(wherePKFlag) { + if q.whereFields != nil { if len(b) > startLen { b = append(b, " AND "...) } - b, err = q.appendWherePK(fmter, b, withAlias) + b, err = q.appendWhereFields(fmter, b, q.whereFields, withAlias) if err != nil { return nil, err } @@ -691,29 +727,30 @@ func appendWhere( return b, nil } -func (q *whereBaseQuery) appendWherePK( - fmter schema.Formatter, b []byte, withAlias bool, +func (q *whereBaseQuery) appendWhereFields( + fmter schema.Formatter, b []byte, fields []*schema.Field, withAlias bool, ) (_ []byte, err error) { if q.table == nil { - err := fmt.Errorf("bun: got %T, but WherePK requires a struct or slice-based model", q.model) - return nil, err - } - if err := q.table.CheckPKs(); err != nil { + err := fmt.Errorf("bun: got %T, but WherePK requires struct or slice-based model", q.model) return nil, err } switch model := q.tableModel.(type) { case *structTableModel: - return q.appendWherePKStruct(fmter, b, model, withAlias) + return q.appendWhereStructFields(fmter, b, model, fields, withAlias) case *sliceTableModel: - return q.appendWherePKSlice(fmter, b, model, withAlias) + return q.appendWhereSliceFields(fmter, b, model, fields, withAlias) + default: + return nil, fmt.Errorf("bun: WhereColumn does not support %T", q.tableModel) } - - return nil, fmt.Errorf("bun: WherePK does not support %T", q.tableModel) } -func (q *whereBaseQuery) appendWherePKStruct( - fmter schema.Formatter, b []byte, model *structTableModel, withAlias bool, +func (q *whereBaseQuery) appendWhereStructFields( + fmter schema.Formatter, + b []byte, + model *structTableModel, + fields []*schema.Field, + withAlias bool, ) (_ []byte, err error) { if !model.strct.IsValid() { return nil, errNilModel @@ -721,7 +758,7 @@ func (q *whereBaseQuery) appendWherePKStruct( isTemplate := fmter.IsNop() b = append(b, '(') - for i, f := range q.table.PKs { + for i, f := range fields { if i > 0 { b = append(b, " AND "...) } @@ -741,18 +778,22 @@ func (q *whereBaseQuery) appendWherePKStruct( return b, nil } -func (q *whereBaseQuery) appendWherePKSlice( - fmter schema.Formatter, b []byte, model *sliceTableModel, withAlias bool, +func (q *whereBaseQuery) appendWhereSliceFields( + fmter schema.Formatter, + b []byte, + model *sliceTableModel, + fields []*schema.Field, + withAlias bool, ) (_ []byte, err error) { - if len(q.table.PKs) > 1 { + if len(fields) > 1 { b = append(b, '(') } if withAlias { - b = appendColumns(b, q.table.SQLAlias, q.table.PKs) + b = appendColumns(b, q.table.SQLAlias, fields) } else { - b = appendColumns(b, "", q.table.PKs) + b = appendColumns(b, "", fields) } - if len(q.table.PKs) > 1 { + if len(fields) > 1 { b = append(b, ')') } @@ -771,10 +812,10 @@ func (q *whereBaseQuery) appendWherePKSlice( el := indirect(slice.Index(i)) - if len(q.table.PKs) > 1 { + if len(fields) > 1 { b = append(b, '(') } - for i, f := range q.table.PKs { + for i, f := range fields { if i > 0 { b = append(b, ", "...) } @@ -784,7 +825,7 @@ func (q *whereBaseQuery) appendWherePKSlice( b = f.AppendValue(fmter, b, el) } } - if len(q.table.PKs) > 1 { + if len(fields) > 1 { b = append(b, ')') } } diff --git a/vendor/github.com/uptrace/bun/query_column_add.go b/vendor/github.com/uptrace/bun/query_column_add.go index 30d76e610..dff514904 100644 --- a/vendor/github.com/uptrace/bun/query_column_add.go +++ b/vendor/github.com/uptrace/bun/query_column_add.go @@ -11,6 +11,8 @@ import ( type AddColumnQuery struct { baseQuery + + ifNotExists bool } func NewAddColumnQuery(db *DB) *AddColumnQuery { @@ -59,6 +61,11 @@ func (q *AddColumnQuery) ColumnExpr(query string, args ...interface{}) *AddColum return q } +func (q *AddColumnQuery) IfNotExists() *AddColumnQuery { + q.ifNotExists = true + return q +} + //------------------------------------------------------------------------------ func (q *AddColumnQuery) Operation() string { @@ -82,6 +89,10 @@ func (q *AddColumnQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte b = append(b, " ADD "...) + if q.ifNotExists { + b = append(b, "IF NOT EXISTS "...) + } + b, err = q.columns[0].AppendQuery(fmter, b) if err != nil { return nil, err @@ -99,11 +110,5 @@ func (q *AddColumnQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Res } query := internal.String(queryBytes) - - res, err := q.exec(ctx, q, query) - if err != nil { - return nil, err - } - - return res, nil + return q.exec(ctx, q, query) } diff --git a/vendor/github.com/uptrace/bun/query_delete.go b/vendor/github.com/uptrace/bun/query_delete.go index a8e14f896..6af3dbd2e 100644 --- a/vendor/github.com/uptrace/bun/query_delete.go +++ b/vendor/github.com/uptrace/bun/query_delete.go @@ -66,8 +66,8 @@ func (q *DeleteQuery) ModelTableExpr(query string, args ...interface{}) *DeleteQ //------------------------------------------------------------------------------ -func (q *DeleteQuery) WherePK() *DeleteQuery { - q.flags = q.flags.Set(wherePKFlag) +func (q *DeleteQuery) WherePK(cols ...string) *DeleteQuery { + q.addWhereCols(cols) return q } diff --git a/vendor/github.com/uptrace/bun/query_select.go b/vendor/github.com/uptrace/bun/query_select.go index 399e3eb0f..ad4db6670 100644 --- a/vendor/github.com/uptrace/bun/query_select.go +++ b/vendor/github.com/uptrace/bun/query_select.go @@ -10,7 +10,6 @@ import ( "strings" "sync" - "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/internal" "github.com/uptrace/bun/schema" ) @@ -116,8 +115,8 @@ func (q *SelectQuery) ExcludeColumn(columns ...string) *SelectQuery { //------------------------------------------------------------------------------ -func (q *SelectQuery) WherePK() *SelectQuery { - q.flags = q.flags.Set(wherePKFlag) +func (q *SelectQuery) WherePK(cols ...string) *SelectQuery { + q.addWhereCols(cols) return q } @@ -542,7 +541,7 @@ func (q *SelectQuery) appendColumns(fmter schema.Formatter, b []byte) (_ []byte, if len(q.table.Fields) > 10 && fmter.IsNop() { b = append(b, q.table.SQLAlias...) b = append(b, '.') - b = dialect.AppendString(b, fmt.Sprintf("%d columns", len(q.table.Fields))) + b = fmter.Dialect().AppendString(b, fmt.Sprintf("%d columns", len(q.table.Fields))) } else { b = appendColumns(b, q.table.SQLAlias, q.table.Fields) } diff --git a/vendor/github.com/uptrace/bun/query_table_create.go b/vendor/github.com/uptrace/bun/query_table_create.go index 78910d5eb..9d4fda104 100644 --- a/vendor/github.com/uptrace/bun/query_table_create.go +++ b/vendor/github.com/uptrace/bun/query_table_create.go @@ -44,7 +44,7 @@ func (q *CreateTableQuery) Model(model interface{}) *CreateTableQuery { return q } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ func (q *CreateTableQuery) Table(tables ...string) *CreateTableQuery { for _, table := range tables { @@ -68,7 +68,7 @@ func (q *CreateTableQuery) ColumnExpr(query string, args ...interface{}) *Create return q } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ func (q *CreateTableQuery) Temp() *CreateTableQuery { q.temp = true @@ -128,7 +128,7 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by if field.NotNull { b = append(b, " NOT NULL"...) } - if q.db.features.Has(feature.AutoIncrement) && field.AutoIncrement { + if fmter.Dialect().Features().Has(feature.AutoIncrement) && field.AutoIncrement { b = append(b, " AUTO_INCREMENT"...) } if field.SQLDefault != "" { @@ -137,8 +137,13 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by } } - for _, col := range q.columns { - b = append(b, ", "...) + for i, col := range q.columns { + // Only pre-pend the comma if we are on subsequent iterations, or if there were fields/columns appended before + // this. This way if we are only appending custom column expressions we will not produce a syntax error with a + // leading comma. + if i > 0 || len(q.table.Fields) > 0 { + b = append(b, ", "...) + } b, err = col.AppendQuery(fmter, b) if err != nil { return nil, err @@ -147,7 +152,7 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by b = q.appendPKConstraint(b, q.table.PKs) b = q.appendUniqueConstraints(fmter, b) - b, err = q.appenFKConstraints(fmter, b) + b, err = q.appendFKConstraints(fmter, b) if err != nil { return nil, err } @@ -226,7 +231,7 @@ func (q *CreateTableQuery) appendUniqueConstraint( return b } -func (q *CreateTableQuery) appenFKConstraints( +func (q *CreateTableQuery) appendFKConstraints( fmter schema.Formatter, b []byte, ) (_ []byte, err error) { for _, fk := range q.fks { @@ -250,7 +255,7 @@ func (q *CreateTableQuery) appendPKConstraint(b []byte, pks []*schema.Field) []b return b } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ func (q *CreateTableQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result, error) { if err := q.beforeCreateTableHook(ctx); err != nil { diff --git a/vendor/github.com/uptrace/bun/query_update.go b/vendor/github.com/uptrace/bun/query_update.go index df583db25..2de4ace9a 100644 --- a/vendor/github.com/uptrace/bun/query_update.go +++ b/vendor/github.com/uptrace/bun/query_update.go @@ -107,8 +107,8 @@ func (q *UpdateQuery) OmitZero() *UpdateQuery { //------------------------------------------------------------------------------ -func (q *UpdateQuery) WherePK() *UpdateQuery { - q.flags = q.flags.Set(wherePKFlag) +func (q *UpdateQuery) WherePK(cols ...string) *UpdateQuery { + q.addWhereCols(cols) return q } diff --git a/vendor/github.com/uptrace/bun/schema/append.go b/vendor/github.com/uptrace/bun/schema/append.go index fccdd17e7..d19f40d50 100644 --- a/vendor/github.com/uptrace/bun/schema/append.go +++ b/vendor/github.com/uptrace/bun/schema/append.go @@ -31,7 +31,7 @@ func Append(fmter Formatter, b []byte, v interface{}) []byte { case float64: return dialect.AppendFloat64(b, v) case string: - return dialect.AppendString(b, v) + return fmter.Dialect().AppendString(b, v) case time.Time: return fmter.Dialect().AppendTime(b, v) case []byte: diff --git a/vendor/github.com/uptrace/bun/schema/append_value.go b/vendor/github.com/uptrace/bun/schema/append_value.go index c93f5b291..5697e35e3 100644 --- a/vendor/github.com/uptrace/bun/schema/append_value.go +++ b/vendor/github.com/uptrace/bun/schema/append_value.go @@ -194,7 +194,7 @@ func appendArrayBytesValue(fmter Formatter, b []byte, v reflect.Value) []byte { } func AppendStringValue(fmter Formatter, b []byte, v reflect.Value) []byte { - return dialect.AppendString(b, v.String()) + return fmter.Dialect().AppendString(b, v.String()) } func AppendJSONValue(fmter Formatter, b []byte, v reflect.Value) []byte { @@ -217,12 +217,12 @@ func appendTimeValue(fmter Formatter, b []byte, v reflect.Value) []byte { func appendIPValue(fmter Formatter, b []byte, v reflect.Value) []byte { ip := v.Interface().(net.IP) - return dialect.AppendString(b, ip.String()) + return fmter.Dialect().AppendString(b, ip.String()) } func appendIPNetValue(fmter Formatter, b []byte, v reflect.Value) []byte { ipnet := v.Interface().(net.IPNet) - return dialect.AppendString(b, ipnet.String()) + return fmter.Dialect().AppendString(b, ipnet.String()) } func appendJSONRawMessageValue(fmter Formatter, b []byte, v reflect.Value) []byte { @@ -230,7 +230,7 @@ func appendJSONRawMessageValue(fmter Formatter, b []byte, v reflect.Value) []byt if bytes == nil { return dialect.AppendNull(b) } - return dialect.AppendString(b, internal.String(bytes)) + return fmter.Dialect().AppendString(b, internal.String(bytes)) } func appendQueryAppenderValue(fmter Formatter, b []byte, v reflect.Value) []byte { diff --git a/vendor/github.com/uptrace/bun/schema/dialect.go b/vendor/github.com/uptrace/bun/schema/dialect.go index f015807dc..134460c3d 100644 --- a/vendor/github.com/uptrace/bun/schema/dialect.go +++ b/vendor/github.com/uptrace/bun/schema/dialect.go @@ -2,8 +2,10 @@ package schema import ( "database/sql" + "encoding/hex" "strconv" "time" + "unicode/utf8" "github.com/uptrace/bun/dialect" "github.com/uptrace/bun/dialect/feature" @@ -24,6 +26,7 @@ type Dialect interface { AppendUint32(b []byte, n uint32) []byte AppendUint64(b []byte, n uint64) []byte AppendTime(b []byte, tm time.Time) []byte + AppendString(b []byte, s string) []byte AppendBytes(b []byte, bs []byte) []byte AppendJSON(b, jsonb []byte) []byte } @@ -47,8 +50,48 @@ func (BaseDialect) AppendTime(b []byte, tm time.Time) []byte { return b } +func (BaseDialect) AppendString(b []byte, s string) []byte { + b = append(b, '\'') + for _, r := range s { + if r == '\000' { + continue + } + + if r == '\'' { + b = append(b, '\'', '\'') + continue + } + + if r < utf8.RuneSelf { + b = append(b, byte(r)) + continue + } + + l := len(b) + if cap(b)-l < utf8.UTFMax { + b = append(b, make([]byte, utf8.UTFMax)...) + } + n := utf8.EncodeRune(b[l:l+utf8.UTFMax], r) + b = b[:l+n] + } + b = append(b, '\'') + return b +} + func (BaseDialect) AppendBytes(b, bs []byte) []byte { - return dialect.AppendBytes(b, bs) + if bs == nil { + return dialect.AppendNull(b) + } + + b = append(b, `'\x`...) + + s := len(b) + b = append(b, make([]byte, hex.EncodedLen(len(bs)))...) + hex.Encode(b[s:], bs) + + b = append(b, '\'') + + return b } func (BaseDialect) AppendJSON(b, jsonb []byte) []byte { diff --git a/vendor/github.com/uptrace/bun/schema/table.go b/vendor/github.com/uptrace/bun/schema/table.go index 2d762e135..642881087 100644 --- a/vendor/github.com/uptrace/bun/schema/table.go +++ b/vendor/github.com/uptrace/bun/schema/table.go @@ -300,11 +300,11 @@ func (t *Table) processBaseModelField(f reflect.StructField) { t.setName(tag.Name) } - if s, ok := tag.Options["select"]; ok { + if s, ok := tag.Option("select"); ok { t.SQLNameForSelects = t.quoteTableName(s) } - if s, ok := tag.Options["alias"]; ok { + if s, ok := tag.Option("alias"); ok { t.Alias = s t.SQLAlias = t.quoteIdent(s) } @@ -315,17 +315,16 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field { tag := tagparser.Parse(f.Tag.Get("bun")) sqlName := internal.Underscore(f.Name) - if tag.Name != "" { + if tag.Name != "" && tag.Name != sqlName { + if isKnownFieldOption(tag.Name) { + internal.Warn.Printf( + "%s.%s tag name %q is also an option name; is it a mistake?", + t.TypeName, f.Name, tag.Name, + ) + } sqlName = tag.Name } - if tag.Name != sqlName && isKnownFieldOption(tag.Name) { - internal.Warn.Printf( - "%s.%s tag name %q is also an option name; is it a mistake?", - t.TypeName, f.Name, tag.Name, - ) - } - for name := range tag.Options { if !isKnownFieldOption(name) { internal.Warn.Printf("%s.%s has unknown tag option: %q", t.TypeName, f.Name, name) @@ -360,20 +359,27 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field { } if v, ok := tag.Options["unique"]; ok { - // Split the value by comma, this will allow multiple names to be specified. - // We can use this to create multiple named unique constraints where a single column - // might be included in multiple constraints. - for _, uniqueName := range strings.Split(v, ",") { + var names []string + if len(v) == 1 { + // Split the value by comma, this will allow multiple names to be specified. + // We can use this to create multiple named unique constraints where a single column + // might be included in multiple constraints. + names = strings.Split(v[0], ",") + } else { + names = v + } + + for _, uniqueName := range names { if t.Unique == nil { t.Unique = make(map[string][]*Field) } t.Unique[uniqueName] = append(t.Unique[uniqueName], field) } } - if s, ok := tag.Options["default"]; ok { + if s, ok := tag.Option("default"); ok { field.SQLDefault = s } - if s, ok := field.Tag.Options["type"]; ok { + if s, ok := field.Tag.Option("type"); ok { field.UserSQLType = s } field.DiscoveredSQLType = DiscoverSQLType(field.IndirectType) @@ -381,7 +387,7 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field { field.Scan = FieldScanner(t.dialect, field) field.IsZero = zeroChecker(field.StructField.Type) - if v, ok := tag.Options["alt"]; ok { + if v, ok := tag.Option("alt"); ok { t.FieldMap[v] = field } @@ -433,7 +439,7 @@ func (t *Table) initRelations() { } func (t *Table) tryRelation(field *Field) bool { - if rel, ok := field.Tag.Options["rel"]; ok { + if rel, ok := field.Tag.Option("rel"); ok { t.initRelation(field, rel) return true } @@ -444,7 +450,7 @@ func (t *Table) tryRelation(field *Field) bool { if field.Tag.HasOption("join") { internal.Warn.Printf( - `%s.%s option "join" requires a relation type`, + `%s.%s "join" option must come together with "rel" option`, t.TypeName, field.GoName, ) } @@ -609,7 +615,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation { } joinTable := t.dialect.Tables().Ref(indirectType(field.IndirectType.Elem())) - polymorphicValue, isPolymorphic := field.Tag.Options["polymorphic"] + polymorphicValue, isPolymorphic := field.Tag.Option("polymorphic") rel := &Relation{ Type: HasManyRelation, Field: field, @@ -706,7 +712,7 @@ func (t *Table) m2mRelation(field *Field) *Relation { panic(err) } - m2mTableName, ok := field.Tag.Options["m2m"] + m2mTableName, ok := field.Tag.Option("m2m") if !ok { panic(fmt.Errorf("bun: %s must have m2m tag option", field.GoName)) } @@ -891,8 +897,14 @@ func removeField(fields []*Field, field *Field) []*Field { return fields } -func parseRelationJoin(join string) ([]string, []string) { - ss := strings.Split(join, ",") +func parseRelationJoin(join []string) ([]string, []string) { + var ss []string + if len(join) == 1 { + ss = strings.Split(join[0], ",") + } else { + ss = join + } + baseColumns := make([]string, len(ss)) joinColumns := make([]string, len(ss)) for i, s := range ss { diff --git a/vendor/github.com/uptrace/bun/schema/tables.go b/vendor/github.com/uptrace/bun/schema/tables.go index 4be856b34..b6215a14a 100644 --- a/vendor/github.com/uptrace/bun/schema/tables.go +++ b/vendor/github.com/uptrace/bun/schema/tables.go @@ -101,13 +101,15 @@ func (t *Tables) table(typ reflect.Type, allowInProgress bool) *Table { return table } - if inProgress.init2() { - t.mu.Lock() - delete(t.inProgress, typ) - t.tables.Store(typ, table) - t.mu.Unlock() + if !inProgress.init2() { + return table } + t.mu.Lock() + delete(t.inProgress, typ) + t.tables.Store(typ, table) + t.mu.Unlock() + t.dialect.OnTable(table) for _, field := range table.FieldMap { diff --git a/vendor/github.com/uptrace/bun/version.go b/vendor/github.com/uptrace/bun/version.go index f13205b85..b5b744224 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.14" + return "1.0.17" } |