[chore] update bun + extras v1.1.16 -> v1.1.17 (#2534)

This commit is contained in:
tobi 2024-01-15 14:08:07 +01:00 committed by GitHub
commit 6433a50582
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1426 additions and 294 deletions

View file

@ -1,3 +1,4 @@
# Patterns for files created by this project.
# For other files, use global gitignore.
*.s3db
.idea

View file

@ -1,3 +1,15 @@
## [1.1.17](https://github.com/uptrace/bun/compare/v1.1.16...v1.1.17) (2024-01-11)
### Features
* add CreateTxSQLMigrations function ([#916](https://github.com/uptrace/bun/issues/916)) ([c68ec7c](https://github.com/uptrace/bun/commit/c68ec7cfc418959eb7c79028be7ac91f97d462ef))
* add Join to UpdateQuery ([#908](https://github.com/uptrace/bun/issues/908)) ([8c4d8be](https://github.com/uptrace/bun/commit/8c4d8be3aa4e64582698b37fd21434b8960dddc0))
* bunslog.QueryHook for Bun logging using `log/slog` ([#904](https://github.com/uptrace/bun/issues/904)) ([4953367](https://github.com/uptrace/bun/commit/495336731da0a995aa28c7bc84345c7825408e48))
* dbfixture.New to accept IDB interface ([#900](https://github.com/uptrace/bun/issues/900)) ([2dee174](https://github.com/uptrace/bun/commit/2dee174bc4d09a45caeeede2885306e5fd10002d))
## [1.1.16](https://github.com/uptrace/bun/compare/v1.1.15...v1.1.16) (2023-09-16)

View file

@ -108,3 +108,7 @@ func (d *Dialect) AppendUint32(b []byte, n uint32) []byte {
func (d *Dialect) AppendUint64(b []byte, n uint64) []byte {
return strconv.AppendInt(b, int64(n), 10)
}
func (d *Dialect) AppendSequence(b []byte, _ *schema.Table, _ *schema.Field) []byte {
return append(b, " GENERATED BY DEFAULT AS IDENTITY"...)
}

View file

@ -2,5 +2,5 @@ package pgdialect
// Version is the current release version.
func Version() string {
return "1.1.16"
return "1.1.17"
}

View file

@ -39,6 +39,7 @@ func New() *Dialect {
feature.InsertOnConflict |
feature.TableNotExists |
feature.SelectExists |
feature.AutoIncrement |
feature.CompositeIn
return d
}
@ -91,6 +92,25 @@ func (d *Dialect) DefaultVarcharLen() int {
return 0
}
// AppendSequence adds AUTOINCREMENT keyword to the column definition. As per [documentation],
// AUTOINCREMENT is only valid for INTEGER PRIMARY KEY, and this method will be a noop for other columns.
//
// Because this is a valid construct:
// CREATE TABLE ("id" INTEGER PRIMARY KEY AUTOINCREMENT);
// and this is not:
// CREATE TABLE ("id" INTEGER AUTOINCREMENT, PRIMARY KEY ("id"));
// AppendSequence adds a primary key constraint as a *side-effect*. Callers should expect it to avoid building invalid SQL.
// SQLite also [does not support] AUTOINCREMENT column in composite primary keys.
//
// [documentation]: https://www.sqlite.org/autoinc.html
// [does not support]: https://stackoverflow.com/a/6793274/14726116
func (d *Dialect) AppendSequence(b []byte, table *schema.Table, field *schema.Field) []byte {
if field.IsPK && len(table.PKs) == 1 && field.CreateTableSQLType == sqltype.Integer {
b = append(b, " PRIMARY KEY AUTOINCREMENT"...)
}
return b
}
func fieldSQLType(field *schema.Field) string {
switch field.DiscoveredSQLType {
case sqltype.SmallInt, sqltype.BigInt:

View file

@ -2,5 +2,5 @@ package sqlitedialect
// Version is the current release version.
func Version() string {
return "1.1.16"
return "1.1.17"
}

View file

@ -158,6 +158,11 @@ SELECT 1
SELECT 2
`
const transactionalSQLTemplate = `SET statement_timeout = 0;
SELECT 1;
`
//------------------------------------------------------------------------------
type MigrationSlice []Migration

View file

@ -267,19 +267,19 @@ func (m *Migrator) CreateGoMigration(
return mf, nil
}
// CreateSQLMigrations creates an up and down SQL migration files.
func (m *Migrator) CreateSQLMigrations(ctx context.Context, name string) ([]*MigrationFile, error) {
// CreateTxSQLMigration creates transactional up and down SQL migration files.
func (m *Migrator) CreateTxSQLMigrations(ctx context.Context, name string) ([]*MigrationFile, error) {
name, err := m.genMigrationName(name)
if err != nil {
return nil, err
}
up, err := m.createSQL(ctx, name+".up.sql")
up, err := m.createSQL(ctx, name+".up.tx.sql", true)
if err != nil {
return nil, err
}
down, err := m.createSQL(ctx, name+".down.sql")
down, err := m.createSQL(ctx, name+".down.tx.sql", true)
if err != nil {
return nil, err
}
@ -287,10 +287,35 @@ func (m *Migrator) CreateSQLMigrations(ctx context.Context, name string) ([]*Mig
return []*MigrationFile{up, down}, nil
}
func (m *Migrator) createSQL(ctx context.Context, fname string) (*MigrationFile, error) {
// CreateSQLMigrations creates up and down SQL migration files.
func (m *Migrator) CreateSQLMigrations(ctx context.Context, name string) ([]*MigrationFile, error) {
name, err := m.genMigrationName(name)
if err != nil {
return nil, err
}
up, err := m.createSQL(ctx, name+".up.sql", false)
if err != nil {
return nil, err
}
down, err := m.createSQL(ctx, name+".down.sql", false)
if err != nil {
return nil, err
}
return []*MigrationFile{up, down}, nil
}
func (m *Migrator) createSQL(ctx context.Context, fname string, transactional bool) (*MigrationFile, error) {
fpath := filepath.Join(m.migrations.getDirectory(), fname)
if err := os.WriteFile(fpath, []byte(sqlTemplate), 0o644); err != nil {
template := sqlTemplate
if transactional {
template = transactionalSQLTemplate
}
if err := os.WriteFile(fpath, []byte(template), 0o644); err != nil {
return nil, err
}

View file

@ -1,6 +1,6 @@
{
"name": "gobun",
"version": "1.1.16",
"version": "1.1.17",
"main": "index.js",
"repository": "git@github.com:uptrace/bun.git",
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>",

View file

@ -332,8 +332,8 @@ func (q *InsertQuery) appendStructValues(
switch {
case isTemplate:
b = append(b, '?')
case (f.IsPtr && f.HasNilValue(strct)) || (f.NullZero && f.HasZeroValue(strct)):
if q.db.features.Has(feature.DefaultPlaceholder) {
case q.marshalsToDefault(f, strct):
if q.db.HasFeature(feature.DefaultPlaceholder) {
b = append(b, "DEFAULT"...)
} else if f.SQLDefault != "" {
b = append(b, f.SQLDefault...)
@ -410,11 +410,9 @@ func (q *InsertQuery) getFields() ([]*schema.Field, error) {
q.addReturningField(f)
continue
}
if f.NotNull && f.SQLDefault == "" {
if (f.IsPtr && f.HasNilValue(strct)) || (f.NullZero && f.HasZeroValue(strct)) {
q.addReturningField(f)
continue
}
if f.NotNull && q.marshalsToDefault(f, strct) {
q.addReturningField(f)
continue
}
fields = append(fields, f)
}
@ -422,6 +420,13 @@ func (q *InsertQuery) getFields() ([]*schema.Field, error) {
return fields, nil
}
// marshalsToDefault checks if the value will be marshaled as DEFAULT or NULL (if DEFAULT placeholder is not supported)
// when appending it to the VALUES clause in place of the given field.
func (q InsertQuery) marshalsToDefault(f *schema.Field, v reflect.Value) bool {
return (f.IsPtr && f.HasNilValue(v)) ||
(f.HasZeroValue(v) && (f.NullZero || f.SQLDefault != ""))
}
func (q *InsertQuery) appendFields(
fmter schema.Formatter, b []byte, fields []*schema.Field,
) []byte {

View file

@ -29,7 +29,7 @@ func NewMergeQuery(db *DB) *MergeQuery {
conn: db.DB,
},
}
if !(q.db.dialect.Name() == dialect.MSSQL || q.db.dialect.Name() == dialect.PG) {
if q.db.dialect.Name() != dialect.MSSQL && q.db.dialect.Name() != dialect.PG {
q.err = errors.New("bun: merge not supported for current dialect")
}
return q

View file

@ -1,6 +1,7 @@
package bun
import (
"bytes"
"context"
"database/sql"
"fmt"
@ -19,6 +20,7 @@ type CreateTableQuery struct {
temp bool
ifNotExists bool
fksFromRel bool // Create foreign keys captured in table's relations.
// varchar changes the default length for VARCHAR columns.
// Because some dialects require that length is always specified for VARCHAR type,
@ -120,21 +122,9 @@ func (q *CreateTableQuery) TableSpace(tablespace string) *CreateTableQuery {
return q
}
// WithForeignKeys adds a FOREIGN KEY clause for each of the model's existing relations.
func (q *CreateTableQuery) WithForeignKeys() *CreateTableQuery {
for _, relation := range q.tableModel.Table().Relations {
if relation.Type == schema.ManyToManyRelation ||
relation.Type == schema.HasManyRelation {
continue
}
q = q.ForeignKey("(?) REFERENCES ? (?) ? ?",
Safe(appendColumns(nil, "", relation.BaseFields)),
relation.JoinTable.SQLName,
Safe(appendColumns(nil, "", relation.JoinFields)),
Safe(relation.OnUpdate),
Safe(relation.OnDelete),
)
}
q.fksFromRel = true
return q
}
@ -157,7 +147,7 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by
b = append(b, "TEMP "...)
}
b = append(b, "TABLE "...)
if q.ifNotExists && fmter.Dialect().Features().Has(feature.TableNotExists) {
if q.ifNotExists && fmter.HasFeature(feature.TableNotExists) {
b = append(b, "IF NOT EXISTS "...)
}
b, err = q.appendFirstTable(fmter, b)
@ -178,19 +168,12 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by
if field.NotNull {
b = append(b, " NOT NULL"...)
}
if field.AutoIncrement {
switch {
case fmter.Dialect().Features().Has(feature.AutoIncrement):
b = append(b, " AUTO_INCREMENT"...)
case fmter.Dialect().Features().Has(feature.Identity):
b = append(b, " IDENTITY"...)
}
}
if field.Identity {
if fmter.Dialect().Features().Has(feature.GeneratedIdentity) {
b = append(b, " GENERATED BY DEFAULT AS IDENTITY"...)
}
if (field.Identity && fmter.HasFeature(feature.GeneratedIdentity)) ||
(field.AutoIncrement && (fmter.HasFeature(feature.AutoIncrement) || fmter.HasFeature(feature.Identity))) {
b = q.db.dialect.AppendSequence(b, q.table, field)
}
if field.SQLDefault != "" {
b = append(b, " DEFAULT "...)
b = append(b, field.SQLDefault...)
@ -210,8 +193,20 @@ func (q *CreateTableQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []by
}
}
b = q.appendPKConstraint(b, q.table.PKs)
// In SQLite AUTOINCREMENT is only valid for INTEGER PRIMARY KEY columns, so it might be that
// a primary key constraint has already been created in dialect.AppendSequence() call above.
// See sqldialect.Dialect.AppendSequence() for more details.
if len(q.table.PKs) > 0 && !bytes.Contains(b, []byte("PRIMARY KEY")) {
b = q.appendPKConstraint(b, q.table.PKs)
}
b = q.appendUniqueConstraints(fmter, b)
if q.fksFromRel {
b, err = q.appendFKConstraintsRel(fmter, b)
if err != nil {
return nil, err
}
}
b, err = q.appendFKConstraints(fmter, b)
if err != nil {
return nil, err
@ -295,13 +290,38 @@ func (q *CreateTableQuery) appendUniqueConstraint(
return b
}
// appendFKConstraintsRel appends a FOREIGN KEY clause for each of the model's existing relations.
func (q *CreateTableQuery) appendFKConstraintsRel(fmter schema.Formatter, b []byte) (_ []byte, err error) {
for _, rel := range q.tableModel.Table().Relations {
if rel.References() {
b, err = q.appendFK(fmter, b, schema.QueryWithArgs{
Query: "(?) REFERENCES ? (?) ? ?",
Args: []interface{}{
Safe(appendColumns(nil, "", rel.BaseFields)),
rel.JoinTable.SQLName,
Safe(appendColumns(nil, "", rel.JoinFields)),
Safe(rel.OnUpdate),
Safe(rel.OnDelete),
},
})
if err != nil {
return nil, err
}
}
}
return b, nil
}
func (q *CreateTableQuery) appendFK(fmter schema.Formatter, b []byte, fk schema.QueryWithArgs) (_ []byte, err error) {
b = append(b, ", FOREIGN KEY "...)
return fk.AppendQuery(fmter, b)
}
func (q *CreateTableQuery) appendFKConstraints(
fmter schema.Formatter, b []byte,
) (_ []byte, err error) {
for _, fk := range q.fks {
b = append(b, ", FOREIGN KEY "...)
b, err = fk.AppendQuery(fmter, b)
if err != nil {
if b, err = q.appendFK(fmter, b, fk); err != nil {
return nil, err
}
}
@ -309,10 +329,6 @@ func (q *CreateTableQuery) appendFKConstraints(
}
func (q *CreateTableQuery) appendPKConstraint(b []byte, pks []*schema.Field) []byte {
if len(pks) == 0 {
return b
}
b = append(b, ", PRIMARY KEY ("...)
b = appendColumns(b, "", pks)
b = append(b, ")"...)
@ -364,3 +380,12 @@ func (q *CreateTableQuery) afterCreateTableHook(ctx context.Context) error {
}
return nil
}
func (q *CreateTableQuery) String() string {
buf, err := q.AppendQuery(q.db.Formatter(), nil)
if err != nil {
panic(err)
}
return string(buf)
}

View file

@ -20,6 +20,7 @@ type UpdateQuery struct {
setQuery
idxHintsQuery
joins []joinQuery
omitZero bool
}
@ -133,6 +134,33 @@ func (q *UpdateQuery) OmitZero() *UpdateQuery {
//------------------------------------------------------------------------------
func (q *UpdateQuery) Join(join string, args ...interface{}) *UpdateQuery {
q.joins = append(q.joins, joinQuery{
join: schema.SafeQuery(join, args),
})
return q
}
func (q *UpdateQuery) JoinOn(cond string, args ...interface{}) *UpdateQuery {
return q.joinOn(cond, args, " AND ")
}
func (q *UpdateQuery) JoinOnOr(cond string, args ...interface{}) *UpdateQuery {
return q.joinOn(cond, args, " OR ")
}
func (q *UpdateQuery) joinOn(cond string, args []interface{}, sep string) *UpdateQuery {
if len(q.joins) == 0 {
q.err = errors.New("bun: query has no joins")
return q
}
j := &q.joins[len(q.joins)-1]
j.on = append(j.on, schema.SafeQueryWithSep(cond, args, sep))
return q
}
//------------------------------------------------------------------------------
func (q *UpdateQuery) WherePK(cols ...string) *UpdateQuery {
q.addWhereCols(cols)
return q
@ -230,6 +258,13 @@ func (q *UpdateQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, e
}
}
for _, j := range q.joins {
b, err = j.AppendQuery(fmter, b)
if err != nil {
return nil, err
}
}
if q.hasFeature(feature.Output) && q.hasReturning() {
b = append(b, " OUTPUT "...)
b, err = q.appendOutput(fmter, b)

View file

@ -31,6 +31,10 @@ type Dialect interface {
AppendJSON(b, jsonb []byte) []byte
AppendBool(b []byte, v bool) []byte
// AppendSequence adds the appropriate instruction for the driver to create a sequence
// from which (autoincremented) values for the column will be generated.
AppendSequence(b []byte, t *Table, f *Field) []byte
// DefaultVarcharLen should be returned for dialects in which specifying VARCHAR length
// is mandatory in queries that modify the schema (CREATE TABLE / ADD COLUMN, etc).
// Dialects that do not have such requirement may return 0, which should be interpreted so by the caller.
@ -177,3 +181,7 @@ func (d *nopDialect) IdentQuote() byte {
func (d *nopDialect) DefaultVarcharLen() int {
return 0
}
func (d *nopDialect) AppendSequence(b []byte, _ *Table, _ *Field) []byte {
return b
}

View file

@ -30,6 +30,12 @@ type Relation struct {
M2MJoinFields []*Field
}
// References returns true if the table to which the Relation belongs needs to declare a foreign key constraint to create the relation.
// For other relations, the constraint is created in either the referencing table (1:N, 'has-many' relations) or a mapping table (N:N, 'm2m' relations).
func (r *Relation) References() bool {
return r.Type == HasOneRelation || r.Type == BelongsToRelation
}
func (r *Relation) String() string {
return fmt.Sprintf("relation=%s", r.Field.GoName)
}

View file

@ -377,7 +377,6 @@ func (t *Table) newField(f reflect.StructField, prefix string, index []int) *Fie
}
if s, ok := tag.Option("default"); ok {
field.SQLDefault = s
field.NullZero = true
}
if s, ok := field.Tag.Option("type"); ok {
field.UserSQLType = s
@ -477,7 +476,7 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
}
rel := &Relation{
Type: HasOneRelation,
Type: BelongsToRelation,
Field: field,
JoinTable: joinTable,
}
@ -571,7 +570,7 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
joinTable := t.dialect.Tables().Ref(field.IndirectType)
rel := &Relation{
Type: BelongsToRelation,
Type: HasOneRelation,
Field: field,
JoinTable: joinTable,
}

View file

@ -2,5 +2,5 @@ package bun
// Version is the current release version.
func Version() string {
return "1.1.16"
return "1.1.17"
}

View file

@ -21,6 +21,12 @@ func Open(driverName, dsn string, opts ...Option) (*sql.DB, error) {
func patchDB(db *sql.DB, dsn string, opts ...Option) (*sql.DB, error) {
dbDriver := db.Driver()
// Close the db since we are about to open a new one.
if err := db.Close(); err != nil {
return nil, err
}
d := newDriver(dbDriver, opts)
if _, ok := dbDriver.(driver.DriverContext); ok {

View file

@ -2,5 +2,5 @@ package otelsql
// Version is the current release version.
func Version() string {
return "0.2.2"
return "0.2.3"
}