Skip to content

Commit

Permalink
fix: support allowzero on the soft delete field
Browse files Browse the repository at this point in the history
  • Loading branch information
vmihailenco committed Oct 14, 2021
1 parent 8ba89d2 commit d0abec7
Show file tree
Hide file tree
Showing 34 changed files with 92 additions and 43 deletions.
41 changes: 34 additions & 7 deletions internal/dbtest/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,20 @@ func TestQuery(t *testing.T) {
User *User `bun:"rel:belongs-to"`
}

type SoftDelete struct {
type SoftDelete1 struct {
bun.BaseModel `bun:"soft_deletes,alias:soft_delete"`

ID int64
DeletedAt time.Time `bun:",soft_delete"`
}

type SoftDelete2 struct {
bun.BaseModel `bun:"soft_deletes,alias:soft_delete"`

ID int64
DeletedAt time.Time `bun:",soft_delete,allowzero"`
}

queries := []func(db *bun.DB) schema.QueryAppender{
func(db *bun.DB) schema.QueryAppender {
return db.NewValues(&Model{42, "hello"})
Expand Down Expand Up @@ -403,19 +412,19 @@ func TestQuery(t *testing.T) {
return db.NewUpdate().Model(new(Model)).Value("foo", "?", "bar").WherePK()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewDelete().Model(new(SoftDelete)).WherePK()
return db.NewDelete().Model(new(SoftDelete1)).WherePK()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewDelete().Model(new(SoftDelete)).WherePK().ForceDelete()
return db.NewDelete().Model(new(SoftDelete1)).WherePK().ForceDelete()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(SoftDelete))
return db.NewSelect().Model(new(SoftDelete1))
},
func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(SoftDelete)).WhereDeleted()
return db.NewSelect().Model(new(SoftDelete1)).WhereDeleted()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(SoftDelete)).WhereAllWithDeleted()
return db.NewSelect().Model(new(SoftDelete1)).WhereAllWithDeleted()
},
func(db *bun.DB) schema.QueryAppender {
models := []Model{
Expand Down Expand Up @@ -552,7 +561,7 @@ func TestQuery(t *testing.T) {
return db.NewInsert().Model(new(Model))
},
func(db *bun.DB) schema.QueryAppender {
return db.NewInsert().Model(new(SoftDelete)).On("CONFLICT DO NOTHING")
return db.NewInsert().Model(new(SoftDelete1)).On("CONFLICT DO NOTHING")
},
func(db *bun.DB) schema.QueryAppender {
return db.NewUpdate().Model(&Model{ID: 42}).OmitZero().WherePK()
Expand All @@ -567,6 +576,24 @@ func TestQuery(t *testing.T) {
func(db *bun.DB) schema.QueryAppender {
return db.NewInsert().ColumnExpr("id, name").Table("dest").Table("src")
},
func(db *bun.DB) schema.QueryAppender {
return db.NewDelete().Model(new(SoftDelete2)).WherePK()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewDelete().Model(new(SoftDelete2)).WherePK().ForceDelete()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(SoftDelete2))
},
func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(SoftDelete2)).WhereDeleted()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(SoftDelete2)).WhereAllWithDeleted()
},
func(db *bun.DB) schema.QueryAppender {
return db.NewInsert().Model(new(SoftDelete2)).On("CONFLICT DO NOTHING")
},
}

timeRE := regexp.MustCompile(`'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+(\+\d{2}:\d{2})?'`)
Expand Down
23 changes: 0 additions & 23 deletions internal/dbtest/soft_delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package dbtest_test

import (
"context"
"database/sql"
"database/sql/driver"
"testing"
"time"

Expand Down Expand Up @@ -32,27 +30,6 @@ func TestSoftDelete(t *testing.T) {
})
}

type CustomTime struct {
Time time.Time
}

var _ driver.Valuer = (*CustomTime)(nil)

func (tm *CustomTime) Value() (driver.Value, error) {
return tm.Time, nil
}

var _ sql.Scanner = (*CustomTime)(nil)

func (tm *CustomTime) Scan(src interface{}) error {
tm.Time, _ = src.(time.Time)
return nil
}

func (tm *CustomTime) IsZero() bool {
return tm.Time.IsZero()
}

type Video struct {
ID int64
Name string
Expand Down
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE `soft_deletes` AS `soft_delete` SET `soft_delete`.`deleted_at` = [TIME] WHERE `soft_delete`.`deleted_at` = '0001-01-01 00:00:00' AND (`soft_delete`.`id` = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-91
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM `soft_deletes` WHERE `deleted_at` != '0001-01-01 00:00:00' AND (`id` = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-92
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT `soft_delete`.`id`, `soft_delete`.`deleted_at` FROM `soft_deletes` AS `soft_delete` WHERE `soft_delete`.`deleted_at` = '0001-01-01 00:00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-93
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT `soft_delete`.`id`, `soft_delete`.`deleted_at` FROM `soft_deletes` AS `soft_delete` WHERE `soft_delete`.`deleted_at` != '0001-01-01 00:00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-94
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT `soft_delete`.`id`, `soft_delete`.`deleted_at` FROM `soft_deletes` AS `soft_delete`
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-95
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO `soft_deletes` (`id`, `deleted_at`) VALUES (DEFAULT, '0001-01-01 00:00:00') ON CONFLICT DO NOTHING
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE `soft_deletes` AS `soft_delete` SET `soft_delete`.`deleted_at` = [TIME] WHERE `soft_delete`.`deleted_at` = '0001-01-01 00:00:00' AND (`soft_delete`.`id` = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-91
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM `soft_deletes` AS `soft_delete` WHERE `soft_delete`.`deleted_at` != '0001-01-01 00:00:00' AND (`soft_delete`.`id` = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-92
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT `soft_delete`.`id`, `soft_delete`.`deleted_at` FROM `soft_deletes` AS `soft_delete` WHERE `soft_delete`.`deleted_at` = '0001-01-01 00:00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-93
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT `soft_delete`.`id`, `soft_delete`.`deleted_at` FROM `soft_deletes` AS `soft_delete` WHERE `soft_delete`.`deleted_at` != '0001-01-01 00:00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-94
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT `soft_delete`.`id`, `soft_delete`.`deleted_at` FROM `soft_deletes` AS `soft_delete`
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-95
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO `soft_deletes` (`id`, `deleted_at`) VALUES (DEFAULT, '0001-01-01 00:00:00') ON CONFLICT DO NOTHING
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE "soft_deletes" AS "soft_delete" SET "deleted_at" = [TIME] WHERE "soft_delete"."deleted_at" = '0001-01-01 00:00:00+00:00' AND ("soft_delete"."id" = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-91
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" != '0001-01-01 00:00:00+00:00' AND ("soft_delete"."id" = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-92
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" = '0001-01-01 00:00:00+00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-93
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" != '0001-01-01 00:00:00+00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-94
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete"
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-95
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO "soft_deletes" AS "soft_delete" ("id", "deleted_at") VALUES (DEFAULT, '0001-01-01 00:00:00+00:00') ON CONFLICT DO NOTHING RETURNING "id"
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE "soft_deletes" AS "soft_delete" SET "deleted_at" = [TIME] WHERE "soft_delete"."deleted_at" = '0001-01-01 00:00:00+00:00' AND ("soft_delete"."id" = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-91
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" != '0001-01-01 00:00:00+00:00' AND ("soft_delete"."id" = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-92
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" = '0001-01-01 00:00:00+00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-93
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" != '0001-01-01 00:00:00+00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-94
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete"
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-95
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO "soft_deletes" AS "soft_delete" ("id", "deleted_at") VALUES (DEFAULT, '0001-01-01 00:00:00+00:00') ON CONFLICT DO NOTHING RETURNING "id"
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UPDATE "soft_deletes" AS "soft_delete" SET "deleted_at" = [TIME] WHERE "soft_delete"."deleted_at" = '0001-01-01 00:00:00+00:00' AND ("soft_delete"."id" = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-91
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" != '0001-01-01 00:00:00+00:00' AND ("soft_delete"."id" = NULL)
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-92
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" = '0001-01-01 00:00:00+00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-93
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete" WHERE "soft_delete"."deleted_at" != '0001-01-01 00:00:00+00:00'
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-94
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT "soft_delete"."id", "soft_delete"."deleted_at" FROM "soft_deletes" AS "soft_delete"
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-95
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO "soft_deletes" AS "soft_delete" ("deleted_at") VALUES ('0001-01-01 00:00:00+00:00') ON CONFLICT DO NOTHING RETURNING "id"
21 changes: 17 additions & 4 deletions query_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"database/sql/driver"
"errors"
"fmt"
"time"

"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal"
Expand Down Expand Up @@ -628,11 +629,23 @@ func (q *whereBaseQuery) appendWhere(
b = append(b, q.tableModel.Table().SQLAlias...)
b = append(b, '.')
}
b = append(b, q.tableModel.Table().SoftDeleteField.SQLName...)
if q.flags.Has(deletedFlag) {
b = append(b, " IS NOT NULL"...)

field := q.tableModel.Table().SoftDeleteField
b = append(b, field.SQLName...)

if field.NullZero {
if q.flags.Has(deletedFlag) {
b = append(b, " IS NOT NULL"...)
} else {
b = append(b, " IS NULL"...)
}
} else {
b = append(b, " IS NULL"...)
if q.flags.Has(deletedFlag) {
b = append(b, " != "...)
} else {
b = append(b, " = "...)
}
b = fmter.Dialect().AppendTime(b, time.Time{})
}
}

Expand Down
20 changes: 11 additions & 9 deletions schema/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,6 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field {
if tag.HasOption("pk") {
field.markAsPK()
}
if tag.HasOption("allowzero") {
if tag.HasOption("nullzero") {
internal.Warn.Printf(
"%s.%s: nullzero and allowzero options are mutually exclusive",
t.TypeName, f.Name,
)
}
field.NullZero = false
}

if v, ok := tag.Options["unique"]; ok {
// Split the value by comma, this will allow multiple names to be specified.
Expand Down Expand Up @@ -385,6 +376,17 @@ func (t *Table) newField(f reflect.StructField, index []int) *Field {
t.UpdateSoftDeleteField = softDeleteFieldUpdater(field)
}

// Check this in the end to undo NullZero.
if tag.HasOption("allowzero") {
if tag.HasOption("nullzero") {
internal.Warn.Printf(
"%s.%s: nullzero and allowzero options are mutually exclusive",
t.TypeName, f.Name,
)
}
field.NullZero = false
}

return field
}

Expand Down

0 comments on commit d0abec7

Please sign in to comment.