From 786bb6bfeba3c12f8b28579d61e4794d9fb3e373 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Sat, 1 Jul 2023 10:38:31 +0300 Subject: [PATCH] feat: add bun.NullZero --- bun.go | 4 ++ internal/dbtest/query_test.go | 3 ++ .../testdata/snapshots/TestQuery-mariadb-158 | 1 + .../snapshots/TestQuery-mssql2019-158 | 1 + .../testdata/snapshots/TestQuery-mysql5-158 | 1 + .../testdata/snapshots/TestQuery-mysql8-158 | 1 + .../testdata/snapshots/TestQuery-pg-158 | 1 + .../testdata/snapshots/TestQuery-pgx-158 | 1 + .../testdata/snapshots/TestQuery-sqlite-158 | 1 + schema/append.go | 21 +++++++++- schema/zerochecker.go | 39 +++++++++++++++++++ 11 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mariadb-158 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mssql2019-158 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mysql5-158 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-mysql8-158 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-pg-158 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-pgx-158 create mode 100644 internal/dbtest/testdata/snapshots/TestQuery-sqlite-158 diff --git a/bun.go b/bun.go index 2cef63fb6..9cb1f1ffe 100644 --- a/bun.go +++ b/bun.go @@ -83,3 +83,7 @@ func SetLogger(logger internal.Logging) { func In(slice interface{}) schema.QueryAppender { return schema.In(slice) } + +func NullZero(value interface{}) schema.QueryAppender { + return schema.NullZero(value) +} diff --git a/internal/dbtest/query_test.go b/internal/dbtest/query_test.go index 24cfd9195..e4a05c51a 100644 --- a/internal/dbtest/query_test.go +++ b/internal/dbtest/query_test.go @@ -986,6 +986,9 @@ func TestQuery(t *testing.T) { // Non-positive VARCHAR length is illegal return db.NewCreateTable().Model((*Model)(nil)).Varchar(-20) }, + func(db *bun.DB) schema.QueryAppender { + return db.NewUpdate().TableExpr("xxx").Set("foo = ?", bun.NullZero("")).Where("1") + }, } 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-158 b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mariadb-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-158 b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mssql2019-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql5-158 b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql5-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-mysql8-158 b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-mysql8-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pg-158 b/internal/dbtest/testdata/snapshots/TestQuery-pg-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-pg-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-pgx-158 b/internal/dbtest/testdata/snapshots/TestQuery-pgx-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-pgx-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/internal/dbtest/testdata/snapshots/TestQuery-sqlite-158 b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-158 new file mode 100644 index 000000000..1b025845f --- /dev/null +++ b/internal/dbtest/testdata/snapshots/TestQuery-sqlite-158 @@ -0,0 +1 @@ +UPDATE xxx SET foo = NULL WHERE (1) diff --git a/schema/append.go b/schema/append.go index 6f633b101..0cfc1180b 100644 --- a/schema/append.go +++ b/schema/append.go @@ -81,7 +81,7 @@ func appendIn(fmter Formatter, b []byte, slice reflect.Value) []byte { sliceLen := slice.Len() if sliceLen == 0 { - return append(b, "NULL"...) + return dialect.AppendNull(b) } for i := 0; i < sliceLen; i++ { @@ -104,3 +104,22 @@ func appendIn(fmter Formatter, b []byte, slice reflect.Value) []byte { } return b } + +//------------------------------------------------------------------------------ + +func NullZero(value interface{}) QueryAppender { + return nullZero{ + value: value, + } +} + +type nullZero struct { + value interface{} +} + +func (nz nullZero) AppendQuery(fmter Formatter, b []byte) (_ []byte, err error) { + if isZero(nz.value) { + return dialect.AppendNull(b), nil + } + return fmter.AppendValue(b, reflect.ValueOf(nz.value)), nil +} diff --git a/schema/zerochecker.go b/schema/zerochecker.go index f088b8c2c..f24e51d30 100644 --- a/schema/zerochecker.go +++ b/schema/zerochecker.go @@ -11,6 +11,45 @@ type isZeroer interface { IsZero() bool } +func isZero(v interface{}) bool { + switch v := v.(type) { + case isZeroer: + return v.IsZero() + case string: + return v == "" + case []byte: + return v == nil + case int: + return v == 0 + case int64: + return v == 0 + case uint: + return v == 0 + case uint64: + return v == 0 + case float32: + return v == 0 + case float64: + return v == 0 + case int8: + return v == 0 + case int16: + return v == 0 + case int32: + return v == 0 + case uint8: + return v == 0 + case uint16: + return v == 0 + case uint32: + return v == 0 + default: + rv := reflect.ValueOf(v) + fn := zeroChecker(rv.Type()) + return fn(rv) + } +} + type IsZeroerFunc func(reflect.Value) bool func zeroChecker(typ reflect.Type) IsZeroerFunc {