Skip to content

Commit

Permalink
Merge pull request #859 from uptrace/feat/null-zero
Browse files Browse the repository at this point in the history
feat: add bun.NullZero
  • Loading branch information
vmihailenco committed Jul 1, 2023
2 parents 4d8e9e3 + 786bb6b commit 838a3bc
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 1 deletion.
4 changes: 4 additions & 0 deletions bun.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
3 changes: 3 additions & 0 deletions internal/dbtest/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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})?'`)
Expand Down
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mariadb-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mssql2019-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-158
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE xxx SET foo = NULL WHERE (1)
21 changes: 20 additions & 1 deletion schema/append.go
Original file line number Diff line number Diff line change
Expand Up @@ -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++ {
Expand All @@ -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
}
39 changes: 39 additions & 0 deletions schema/zerochecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 838a3bc

Please sign in to comment.