From ee6f1d0cfc83b65f332a8df6c4442826b05fa603 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 29 Nov 2023 15:03:27 +0100 Subject: [PATCH 1/5] test: capture bug --- internal/dbtest/query_test.go | 10 ++++++++++ .../dbtest/testdata/snapshots/TestQuery-mariadb-165 | 1 + .../dbtest/testdata/snapshots/TestQuery-mssql2019-165 | 1 + .../dbtest/testdata/snapshots/TestQuery-mysql5-165 | 1 + .../dbtest/testdata/snapshots/TestQuery-mysql8-165 | 1 + internal/dbtest/testdata/snapshots/TestQuery-pg-165 | 1 + internal/dbtest/testdata/snapshots/TestQuery-pgx-165 | 1 + .../dbtest/testdata/snapshots/TestQuery-sqlite-165 | 1 + 8 files changed, 17 insertions(+) create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mariadb-165 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mssql2019-165 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mysql5-165 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mysql8-165 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-pg-165 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-pgx-165 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-sqlite-165 diff --git a/internal/dbtest/query_test.go b/internal/dbtest/query_test.go index 3abe2df59..841ed683e 100644 --- a/internal/dbtest/query_test.go +++ b/internal/dbtest/query_test.go @@ -1016,6 +1016,16 @@ func TestQuery(t *testing.T) { _ = q.String() return q }, + func(db *bun.DB) schema.QueryAppender { + return db.NewUpdate().Model(&struct { + bun.BaseModel `bun:"table:accounts"` + ID int `bun:"id,pk,autoincrement"` + IsActive bool `bun:"is_active,notnull,default:true"` + }{ + ID: 1, + IsActive: false, + }).Column("is_active").WherePK() + }, } timeRE := regexp.MustCompile(`'2\d{3}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+\d{2}:\d{2})?'`) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-165 b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-165 new file mode 100644 index 000000000..e9af7778a --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-165 @@ -0,0 +1 @@ +UPDATE `accounts` SET `is_active` = FALSE WHERE (`accounts`.`id` = 1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-165 b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-165 new file mode 100644 index 000000000..17ca79039 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-165 @@ -0,0 +1 @@ +UPDATE "accounts" SET "is_active" = 0 WHERE ("id" = 1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-165 b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-165 new file mode 100644 index 000000000..e9af7778a --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-165 @@ -0,0 +1 @@ +UPDATE `accounts` SET `is_active` = FALSE WHERE (`accounts`.`id` = 1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-165 b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-165 new file mode 100644 index 000000000..e9af7778a --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-165 @@ -0,0 +1 @@ +UPDATE `accounts` SET `is_active` = FALSE WHERE (`accounts`.`id` = 1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pg-165 b/internal/dbtest/testdata/snapshots/TestQuery-pg-165 new file mode 100644 index 000000000..a12b64292 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-pg-165 @@ -0,0 +1 @@ +UPDATE "accounts" AS "accounts" SET "is_active" = FALSE WHERE ("accounts"."id" = 1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pgx-165 b/internal/dbtest/testdata/snapshots/TestQuery-pgx-165 new file mode 100644 index 000000000..a12b64292 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-pgx-165 @@ -0,0 +1 @@ +UPDATE "accounts" AS "accounts" SET "is_active" = FALSE WHERE ("accounts"."id" = 1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-165 b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-165 new file mode 100644 index 000000000..a12b64292 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-165 @@ -0,0 +1 @@ +UPDATE "accounts" AS "accounts" SET "is_active" = FALSE WHERE ("accounts"."id" = 1) From 586b2402759c5235c92ccfe5897765dc1aa963f4 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 29 Nov 2023 16:05:16 +0100 Subject: [PATCH 2/5] test: add test cases for nullzero + default --- internal/dbtest/query_test.go | 27 ++++++++++++++++--- .../testdata/snapshots/TestQuery-mariadb-166 | 1 + .../testdata/snapshots/TestQuery-mariadb-51 | 2 +- .../testdata/snapshots/TestQuery-mariadb-52 | 2 +- .../snapshots/TestQuery-mssql2019-166 | 1 + .../testdata/snapshots/TestQuery-mssql2019-51 | 2 +- .../testdata/snapshots/TestQuery-mssql2019-52 | 2 +- .../testdata/snapshots/TestQuery-mysql5-166 | 1 + .../testdata/snapshots/TestQuery-mysql5-51 | 2 +- .../testdata/snapshots/TestQuery-mysql5-52 | 2 +- .../testdata/snapshots/TestQuery-mysql8-166 | 1 + .../testdata/snapshots/TestQuery-mysql8-51 | 2 +- .../testdata/snapshots/TestQuery-mysql8-52 | 2 +- .../testdata/snapshots/TestQuery-pg-166 | 1 + .../dbtest/testdata/snapshots/TestQuery-pg-51 | 2 +- .../dbtest/testdata/snapshots/TestQuery-pg-52 | 2 +- .../testdata/snapshots/TestQuery-pgx-166 | 1 + .../testdata/snapshots/TestQuery-pgx-51 | 2 +- .../testdata/snapshots/TestQuery-pgx-52 | 2 +- .../testdata/snapshots/TestQuery-sqlite-166 | 1 + .../testdata/snapshots/TestQuery-sqlite-51 | 2 +- .../testdata/snapshots/TestQuery-sqlite-52 | 2 +- 22 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mariadb-166 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mssql2019-166 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mysql5-166 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mysql8-166 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-pg-166 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-pgx-166 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-sqlite-166 diff --git a/internal/dbtest/query_test.go b/internal/dbtest/query_test.go index 841ed683e..e509973b4 100644 --- a/internal/dbtest/query_test.go +++ b/internal/dbtest/query_test.go @@ -331,20 +331,27 @@ func TestQuery(t *testing.T) { Where("model.id = _data.id") }, func(db *bun.DB) schema.QueryAppender { + // "nullzero" marshalls zero values as DEFAULT or NULL (if DEFAULT placeholder is not supported) + // DB drivers that support DEFAULT placeholder resolve it to NULL for columns that do not have a DEFAULT value. type Model struct { Int int64 `bun:",nullzero"` Uint uint64 `bun:",nullzero"` Str string `bun:",nullzero"` Time time.Time `bun:",nullzero"` + Bool bool `bun:",nullzero"` + // EmptyStr string `bun:",nullzero,default:''"` -- same as Str } return db.NewInsert().Model(new(Model)) }, func(db *bun.DB) schema.QueryAppender { + // "nullzero,default" is equivalent to "default", marshalling zero values to DEFAULT type Model struct { - Int int64 `bun:",nullzero,default:42"` - Uint uint64 `bun:",nullzero,default:42"` - Str string `bun:",nullzero,default:'hello'"` - Time time.Time `bun:",nullzero,default:now()"` + Int int64 `bun:",nullzero,default:42"` + Uint uint64 `bun:",nullzero,default:42"` + Str string `bun:",nullzero,default:'hello'"` + Time time.Time `bun:",nullzero,default:now()"` + Bool bool `bun:",nullzero,default:true"` + EmptyStr string `bun:",nullzero,default:''"` } return db.NewInsert().Model(new(Model)) }, @@ -1026,6 +1033,18 @@ func TestQuery(t *testing.T) { IsActive: false, }).Column("is_active").WherePK() }, + func(db *bun.DB) schema.QueryAppender { + // "default" marshalls zero values as DEFAULT or specified default value + type Model struct { + Int int64 `bun:",default:42"` + Uint uint64 `bun:",default:42"` + Str string `bun:",default:'hello'"` + Time time.Time `bun:",default:now()"` + Bool bool `bun:",default:true"` + EmptyStr string `bun:",default:''"` + } + return db.NewInsert().Model(new(Model)) + }, } timeRE := regexp.MustCompile(`'2\d{3}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+\d{2}:\d{2})?'`) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-166 b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-166 new file mode 100644 index 000000000..80790e98f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-166 @@ -0,0 +1 @@ +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time`, `bool`, `empty_str` diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 index 9e86633bd..c2b0cb082 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time` +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time`, `bool` diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-52 b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-52 index 9e86633bd..80790e98f 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-52 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time` +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time`, `bool`, `empty_str` diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-166 b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-166 new file mode 100644 index 000000000..280b492a1 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-166 @@ -0,0 +1 @@ +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 index a2c178a81..80ad75d70 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-52 b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-52 index a2c178a81..280b492a1 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-52 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-166 b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-166 new file mode 100644 index 000000000..258004f51 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-166 @@ -0,0 +1 @@ +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 index 6b0ce61b7..b1621f1c7 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-52 b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-52 index 6b0ce61b7..258004f51 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-52 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-166 b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-166 new file mode 100644 index 000000000..258004f51 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-166 @@ -0,0 +1 @@ +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 index 6b0ce61b7..b1621f1c7 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-52 b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-52 index 6b0ce61b7..258004f51 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-52 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pg-166 b/internal/dbtest/testdata/snapshots/TestQuery-pg-166 new file mode 100644 index 000000000..af8c1f986 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-pg-166 @@ -0,0 +1 @@ +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pg-51 b/internal/dbtest/testdata/snapshots/TestQuery-pg-51 index 2c723bfe2..55e65e615 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-pg-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-pg-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time" +INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pg-52 b/internal/dbtest/testdata/snapshots/TestQuery-pg-52 index 2c723bfe2..af8c1f986 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-pg-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-pg-52 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time" +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pgx-166 b/internal/dbtest/testdata/snapshots/TestQuery-pgx-166 new file mode 100644 index 000000000..af8c1f986 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-pgx-166 @@ -0,0 +1 @@ +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 b/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 index 2c723bfe2..55e65e615 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time" +INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pgx-52 b/internal/dbtest/testdata/snapshots/TestQuery-pgx-52 index 2c723bfe2..af8c1f986 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-pgx-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-pgx-52 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time" +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-166 b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-166 new file mode 100644 index 000000000..77170bae8 --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-166 @@ -0,0 +1 @@ +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (42, 42, 'hello', now(), true, '') RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 index 7be44e21e..cbef01565 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (NULL, NULL, NULL, NULL) RETURNING "int", "uint", "str", "time" +INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (NULL, NULL, NULL, NULL, NULL) RETURNING "int", "uint", "str", "time", "bool" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-52 b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-52 index 1fb329522..77170bae8 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-52 +++ b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-52 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time") VALUES (42, 42, 'hello', now()) RETURNING "int", "uint", "str", "time" +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (42, 42, 'hello', now(), true, '') RETURNING "int", "uint", "str", "time", "bool", "empty_str" From 4490dbf0dd30c54074c4a78a582ee1a085a1ab17 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 29 Nov 2023 19:08:32 +0100 Subject: [PATCH 3/5] fix: marshal bool zero values as sql boolean --- internal/dbtest/query_test.go | 4 ++-- query_insert.go | 4 ++-- schema/table.go | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/dbtest/query_test.go b/internal/dbtest/query_test.go index e509973b4..016763a78 100644 --- a/internal/dbtest/query_test.go +++ b/internal/dbtest/query_test.go @@ -339,12 +339,12 @@ func TestQuery(t *testing.T) { Str string `bun:",nullzero"` Time time.Time `bun:",nullzero"` Bool bool `bun:",nullzero"` - // EmptyStr string `bun:",nullzero,default:''"` -- same as Str + // EmptyStr string `bun:",nullzero"` -- same as Str } return db.NewInsert().Model(new(Model)) }, func(db *bun.DB) schema.QueryAppender { - // "nullzero,default" is equivalent to "default", marshalling zero values to DEFAULT + // "nullzero,default" is equivalent to "default", marshalling zero values to DEFAULT type Model struct { Int int64 `bun:",nullzero,default:42"` Uint uint64 `bun:",nullzero,default:42"` diff --git a/query_insert.go b/query_insert.go index 7cf053756..f64bff21b 100644 --- a/query_insert.go +++ b/query_insert.go @@ -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 f.IsPtr && f.HasNilValue(strct), f.HasZeroValue(strct) && (f.NullZero || f.SQLDefault != ""): + if q.db.HasFeature(feature.DefaultPlaceholder) { b = append(b, "DEFAULT"...) } else if f.SQLDefault != "" { b = append(b, f.SQLDefault...) diff --git a/schema/table.go b/schema/table.go index c36198950..e6986f109 100644 --- a/schema/table.go +++ b/schema/table.go @@ -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 From 7fd5cd4df5e5b4f6bdd038ffd2a938d964a4409e Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 29 Nov 2023 19:22:05 +0100 Subject: [PATCH 4/5] refactor: move complex conditional to a method The `f.SQLDefault == ""` part seems redundant before addReturningField, as RETURNING makes sense for a field that was given its default value. --- internal/dbtest/query_test.go | 6 +++--- query_insert.go | 17 +++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/internal/dbtest/query_test.go b/internal/dbtest/query_test.go index 016763a78..2143bb6de 100644 --- a/internal/dbtest/query_test.go +++ b/internal/dbtest/query_test.go @@ -331,8 +331,8 @@ func TestQuery(t *testing.T) { Where("model.id = _data.id") }, func(db *bun.DB) schema.QueryAppender { - // "nullzero" marshalls zero values as DEFAULT or NULL (if DEFAULT placeholder is not supported) - // DB drivers that support DEFAULT placeholder resolve it to NULL for columns that do not have a DEFAULT value. + // "nullzero" marshals zero values as DEFAULT or NULL (if DEFAULT placeholder is not supported) + // DB drivers which support DEFAULT placeholder resolve it to NULL for columns that do not have a DEFAULT value. type Model struct { Int int64 `bun:",nullzero"` Uint uint64 `bun:",nullzero"` @@ -1034,7 +1034,7 @@ func TestQuery(t *testing.T) { }).Column("is_active").WherePK() }, func(db *bun.DB) schema.QueryAppender { - // "default" marshalls zero values as DEFAULT or specified default value + // "default" marshals zero values as DEFAULT or the specified default value type Model struct { Int int64 `bun:",default:42"` Uint uint64 `bun:",default:42"` diff --git a/query_insert.go b/query_insert.go index f64bff21b..6d38a4efe 100644 --- a/query_insert.go +++ b/query_insert.go @@ -332,7 +332,7 @@ func (q *InsertQuery) appendStructValues( switch { case isTemplate: b = append(b, '?') - case f.IsPtr && f.HasNilValue(strct), f.HasZeroValue(strct) && (f.NullZero || f.SQLDefault != ""): + case q.marshalsToDefault(f, strct): if q.db.HasFeature(feature.DefaultPlaceholder) { b = append(b, "DEFAULT"...) } else if 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 { From 176c86fb3e33571a6dfa56a0cb2c16f8d9e1a677 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Sun, 7 Jan 2024 13:25:29 +0100 Subject: [PATCH 5/5] test: add test case for empty string + nullzero --- internal/dbtest/query_test.go | 12 ++++++------ .../dbtest/testdata/snapshots/TestQuery-mariadb-51 | 2 +- .../dbtest/testdata/snapshots/TestQuery-mssql2019-51 | 2 +- .../dbtest/testdata/snapshots/TestQuery-mysql5-51 | 2 +- .../dbtest/testdata/snapshots/TestQuery-mysql8-51 | 2 +- internal/dbtest/testdata/snapshots/TestQuery-pg-51 | 2 +- internal/dbtest/testdata/snapshots/TestQuery-pgx-51 | 2 +- .../dbtest/testdata/snapshots/TestQuery-sqlite-51 | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/dbtest/query_test.go b/internal/dbtest/query_test.go index 2143bb6de..65a7d8f06 100644 --- a/internal/dbtest/query_test.go +++ b/internal/dbtest/query_test.go @@ -334,12 +334,12 @@ func TestQuery(t *testing.T) { // "nullzero" marshals zero values as DEFAULT or NULL (if DEFAULT placeholder is not supported) // DB drivers which support DEFAULT placeholder resolve it to NULL for columns that do not have a DEFAULT value. type Model struct { - Int int64 `bun:",nullzero"` - Uint uint64 `bun:",nullzero"` - Str string `bun:",nullzero"` - Time time.Time `bun:",nullzero"` - Bool bool `bun:",nullzero"` - // EmptyStr string `bun:",nullzero"` -- same as Str + Int int64 `bun:",nullzero"` + Uint uint64 `bun:",nullzero"` + Str string `bun:",nullzero"` + Time time.Time `bun:",nullzero"` + Bool bool `bun:",nullzero"` + EmptyStr string `bun:",nullzero"` // same as Str } return db.NewInsert().Model(new(Model)) }, diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 index c2b0cb082..80790e98f 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-51 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time`, `bool` +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING `int`, `uint`, `str`, `time`, `bool`, `empty_str` diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 index 80ad75d70..280b492a1 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 index b1621f1c7..258004f51 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-51 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 index b1621f1c7..258004f51 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-51 @@ -1 +1 @@ -INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) +INSERT INTO `models` (`int`, `uint`, `str`, `time`, `bool`, `empty_str`) VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pg-51 b/internal/dbtest/testdata/snapshots/TestQuery-pg-51 index 55e65e615..af8c1f986 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-pg-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-pg-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool" +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 b/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 index 55e65e615..af8c1f986 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-pgx-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool" +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) RETURNING "int", "uint", "str", "time", "bool", "empty_str" diff --git a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 index cbef01565..fd15e70ab 100644 --- a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 +++ b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-51 @@ -1 +1 @@ -INSERT INTO "models" ("int", "uint", "str", "time", "bool") VALUES (NULL, NULL, NULL, NULL, NULL) RETURNING "int", "uint", "str", "time", "bool" +INSERT INTO "models" ("int", "uint", "str", "time", "bool", "empty_str") VALUES (NULL, NULL, NULL, NULL, NULL, NULL) RETURNING "int", "uint", "str", "time", "bool", "empty_str"