fork github.com/doug-martin
This commit is contained in:
+496
@@ -0,0 +1,496 @@
|
||||
package db_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dbv2 "git.fsdpf.net/go/db/v2"
|
||||
"git.fsdpf.net/go/db/v2/exp"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type githubIssuesSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (gis *githubIssuesSuite) AfterTest(_, _ string) {
|
||||
dbv2.SetColumnRenameFunction(strings.ToLower)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/49
|
||||
func (gis *githubIssuesSuite) TestIssue49() {
|
||||
dialect := dbv2.Dialect("default")
|
||||
|
||||
filters := dbv2.Or()
|
||||
sql, args, err := dialect.From("table").Where(filters).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(args)
|
||||
gis.Equal(`SELECT * FROM "table"`, sql)
|
||||
|
||||
sql, args, err = dialect.From("table").Where(dbv2.Ex{}).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(args)
|
||||
gis.Equal(`SELECT * FROM "table"`, sql)
|
||||
|
||||
sql, args, err = dialect.From("table").Where(dbv2.ExOr{}).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(args)
|
||||
gis.Equal(`SELECT * FROM "table"`, sql)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/115
|
||||
func (gis *githubIssuesSuite) TestIssue115() {
|
||||
type TestStruct struct {
|
||||
Field string
|
||||
}
|
||||
dbv2.SetColumnRenameFunction(func(col string) string {
|
||||
return ""
|
||||
})
|
||||
|
||||
_, _, err := dbv2.Insert("test").Rows(TestStruct{Field: "hello"}).ToSQL()
|
||||
gis.EqualError(err, `db: a empty identifier was encountered, please specify a "schema", "table" or "column"`)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/118
|
||||
func (gis *githubIssuesSuite) TestIssue118_withEmbeddedStructWithoutExportedFields() {
|
||||
// struct is in a custom package
|
||||
type SimpleRole struct {
|
||||
permissions []string //nolint:structcheck,unused //needed for test
|
||||
}
|
||||
|
||||
// .....
|
||||
|
||||
type Role struct {
|
||||
*SimpleRole
|
||||
|
||||
ID string `json:"id" db:"id" ff:"skipinsert"`
|
||||
Key string `json:"key" db:"key"`
|
||||
Name string `json:"name" db:"name"`
|
||||
CreatedAt time.Time `json:"-" db:"created_at" ff:"skipinsert"`
|
||||
}
|
||||
|
||||
rUser := &Role{
|
||||
Key: `user`,
|
||||
Name: `User role`,
|
||||
}
|
||||
|
||||
sql, arg, err := dbv2.Insert(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Rows(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(`INSERT INTO "rbac_roles" ("key", "name") VALUES ('user', 'User role') RETURNING "id"`, sql)
|
||||
|
||||
sql, arg, err = dbv2.Update(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Set(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(
|
||||
`UPDATE "rbac_roles" SET "created_at"='0001-01-01T00:00:00Z',"id"='',"key"='user',"name"='User role' RETURNING "id"`,
|
||||
sql,
|
||||
)
|
||||
|
||||
rUser = &Role{
|
||||
SimpleRole: &SimpleRole{},
|
||||
Key: `user`,
|
||||
Name: `User role`,
|
||||
}
|
||||
|
||||
sql, arg, err = dbv2.Insert(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Rows(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(`INSERT INTO "rbac_roles" ("key", "name") VALUES ('user', 'User role') RETURNING "id"`, sql)
|
||||
|
||||
sql, arg, err = dbv2.Update(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Set(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(
|
||||
`UPDATE "rbac_roles" SET `+
|
||||
`"created_at"='0001-01-01T00:00:00Z',"id"='',"key"='user',"name"='User role' RETURNING "id"`,
|
||||
sql,
|
||||
)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/118
|
||||
func (gis *githubIssuesSuite) TestIssue118_withNilEmbeddedStructWithExportedFields() {
|
||||
// struct is in a custom package
|
||||
type SimpleRole struct {
|
||||
permissions []string //nolint:structcheck,unused // needed for test
|
||||
IDStr string
|
||||
}
|
||||
|
||||
// .....
|
||||
|
||||
type Role struct {
|
||||
*SimpleRole
|
||||
|
||||
ID string `json:"id" db:"id" ff:"skipinsert"`
|
||||
Key string `json:"key" db:"key"`
|
||||
Name string `json:"name" db:"name"`
|
||||
CreatedAt time.Time `json:"-" db:"created_at" ff:"skipinsert"`
|
||||
}
|
||||
|
||||
rUser := &Role{
|
||||
Key: `user`,
|
||||
Name: `User role`,
|
||||
}
|
||||
sql, arg, err := dbv2.Insert(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Rows(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
// it should not insert fields on nil embedded pointers
|
||||
gis.Equal(`INSERT INTO "rbac_roles" ("key", "name") VALUES ('user', 'User role') RETURNING "id"`, sql)
|
||||
|
||||
sql, arg, err = dbv2.Update(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Set(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
// it should not insert fields on nil embedded pointers
|
||||
gis.Equal(
|
||||
`UPDATE "rbac_roles" SET "created_at"='0001-01-01T00:00:00Z',"id"='',"key"='user',"name"='User role' RETURNING "id"`,
|
||||
sql,
|
||||
)
|
||||
|
||||
rUser = &Role{
|
||||
SimpleRole: &SimpleRole{},
|
||||
Key: `user`,
|
||||
Name: `User role`,
|
||||
}
|
||||
sql, arg, err = dbv2.Insert(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Rows(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
// it should not insert fields on nil embedded pointers
|
||||
gis.Equal(
|
||||
`INSERT INTO "rbac_roles" ("idstr", "key", "name") VALUES ('', 'user', 'User role') RETURNING "id"`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, arg, err = dbv2.Update(`rbac_roles`).
|
||||
Returning(dbv2.C(`id`)).
|
||||
Set(rUser).
|
||||
ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
// it should not insert fields on nil embedded pointers
|
||||
gis.Equal(
|
||||
`UPDATE "rbac_roles" SET `+
|
||||
`"created_at"='0001-01-01T00:00:00Z',"id"='',"idstr"='',"key"='user',"name"='User role' RETURNING "id"`,
|
||||
sql,
|
||||
)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/118
|
||||
func (gis *githubIssuesSuite) TestIssue140() {
|
||||
sql, arg, err := dbv2.Insert(`test`).Returning().ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(`INSERT INTO "test" DEFAULT VALUES`, sql)
|
||||
|
||||
sql, arg, err = dbv2.Update(`test`).Set(dbv2.Record{"a": "b"}).Returning().ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(
|
||||
`UPDATE "test" SET "a"='b'`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, arg, err = dbv2.Delete(`test`).Returning().ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(
|
||||
`DELETE FROM "test"`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, arg, err = dbv2.Insert(`test`).Returning(nil).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(`INSERT INTO "test" DEFAULT VALUES`, sql)
|
||||
|
||||
sql, arg, err = dbv2.Update(`test`).Set(dbv2.Record{"a": "b"}).Returning(nil).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(
|
||||
`UPDATE "test" SET "a"='b'`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, arg, err = dbv2.Delete(`test`).Returning(nil).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(arg)
|
||||
gis.Equal(
|
||||
`DELETE FROM "test"`,
|
||||
sql,
|
||||
)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/164
|
||||
func (gis *githubIssuesSuite) TestIssue164() {
|
||||
insertDs := dbv2.Insert("foo").Rows(dbv2.Record{"user_id": 10}).Returning("id")
|
||||
|
||||
ds := dbv2.From("bar").
|
||||
With("ins", insertDs).
|
||||
Select("bar_name").
|
||||
Where(dbv2.Ex{"bar.user_id": dbv2.I("ins.user_id")})
|
||||
|
||||
sql, args, err := ds.ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(args)
|
||||
gis.Equal(
|
||||
`WITH ins AS (INSERT INTO "foo" ("user_id") VALUES (10) RETURNING "id") `+
|
||||
`SELECT "bar_name" FROM "bar" WHERE ("bar"."user_id" = "ins"."user_id")`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal([]interface{}{int64(10)}, args)
|
||||
gis.Equal(
|
||||
`WITH ins AS (INSERT INTO "foo" ("user_id") VALUES (?) RETURNING "id")`+
|
||||
` SELECT "bar_name" FROM "bar" WHERE ("bar"."user_id" = "ins"."user_id")`,
|
||||
sql,
|
||||
)
|
||||
|
||||
updateDs := dbv2.Update("foo").Set(dbv2.Record{"bar": "baz"}).Returning("id")
|
||||
|
||||
ds = dbv2.From("bar").
|
||||
With("upd", updateDs).
|
||||
Select("bar_name").
|
||||
Where(dbv2.Ex{"bar.user_id": dbv2.I("upd.user_id")})
|
||||
|
||||
sql, args, err = ds.ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(args)
|
||||
gis.Equal(
|
||||
`WITH upd AS (UPDATE "foo" SET "bar"='baz' RETURNING "id") SELECT "bar_name" FROM "bar" WHERE ("bar"."user_id" = "upd"."user_id")`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal([]interface{}{"baz"}, args)
|
||||
gis.Equal(
|
||||
`WITH upd AS (UPDATE "foo" SET "bar"=? RETURNING "id") SELECT "bar_name" FROM "bar" WHERE ("bar"."user_id" = "upd"."user_id")`,
|
||||
sql,
|
||||
)
|
||||
|
||||
deleteDs := dbv2.Delete("foo").Where(dbv2.Ex{"bar": "baz"}).Returning("id")
|
||||
|
||||
ds = dbv2.From("bar").
|
||||
With("del", deleteDs).
|
||||
Select("bar_name").
|
||||
Where(dbv2.Ex{"bar.user_id": dbv2.I("del.user_id")})
|
||||
|
||||
sql, args, err = ds.ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Empty(args)
|
||||
gis.Equal(
|
||||
`WITH del AS (DELETE FROM "foo" WHERE ("bar" = 'baz') RETURNING "id")`+
|
||||
` SELECT "bar_name" FROM "bar" WHERE ("bar"."user_id" = "del"."user_id")`,
|
||||
sql,
|
||||
)
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal([]interface{}{"baz"}, args)
|
||||
gis.Equal(
|
||||
`WITH del AS (DELETE FROM "foo" WHERE ("bar" = ?) RETURNING "id")`+
|
||||
` SELECT "bar_name" FROM "bar" WHERE ("bar"."user_id" = "del"."user_id")`,
|
||||
sql,
|
||||
)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/177
|
||||
func (gis *githubIssuesSuite) TestIssue177() {
|
||||
ds := dbv2.Dialect("postgres").
|
||||
From("ins1").
|
||||
With("ins1",
|
||||
dbv2.Dialect("postgres").
|
||||
Insert("account").
|
||||
Rows(dbv2.Record{"email": "email@email.com", "status": "active", "uuid": "XXX-XXX-XXXX"}).
|
||||
Returning("*"),
|
||||
).
|
||||
With("ins2",
|
||||
dbv2.Dialect("postgres").
|
||||
Insert("account_user").
|
||||
Cols("account_id", "user_id").
|
||||
FromQuery(dbv2.Dialect("postgres").
|
||||
From("ins1").
|
||||
Select(
|
||||
"id",
|
||||
dbv2.V(1001),
|
||||
),
|
||||
),
|
||||
).
|
||||
Select("*")
|
||||
sql, args, err := ds.ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal(`WITH ins1 AS (`+
|
||||
`INSERT INTO "account" ("email", "status", "uuid") VALUES ('email@email.com', 'active', 'XXX-XXX-XXXX') RETURNING *),`+
|
||||
` ins2 AS (INSERT INTO "account_user" ("account_id", "user_id") SELECT "id", 1001 FROM "ins1")`+
|
||||
` SELECT * FROM "ins1"`, sql)
|
||||
gis.Len(args, 0)
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal(`WITH ins1 AS (INSERT INTO "account" ("email", "status", "uuid") VALUES ($1, $2, $3) RETURNING *), ins2`+
|
||||
` AS (INSERT INTO "account_user" ("account_id", "user_id") SELECT "id", $4 FROM "ins1") SELECT * FROM "ins1"`, sql)
|
||||
gis.Equal(args, []interface{}{"email@email.com", "active", "XXX-XXX-XXXX", int64(1001)})
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/183
|
||||
func (gis *githubIssuesSuite) TestIssue184() {
|
||||
expectedErr := fmt.Errorf("an error")
|
||||
testCases := []struct {
|
||||
ds exp.AppendableExpression
|
||||
}{
|
||||
{ds: dbv2.From("test").As("t").SetError(expectedErr)},
|
||||
{ds: dbv2.Insert("test").Rows(dbv2.Record{"foo": "bar"}).Returning("foo").SetError(expectedErr)},
|
||||
{ds: dbv2.Update("test").Set(dbv2.Record{"foo": "bar"}).Returning("foo").SetError(expectedErr)},
|
||||
{ds: dbv2.Update("test").Set(dbv2.Record{"foo": "bar"}).Returning("foo").SetError(expectedErr)},
|
||||
{ds: dbv2.Delete("test").Returning("foo").SetError(expectedErr)},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ds := dbv2.From(tc.ds)
|
||||
sql, args, err := ds.ToSQL()
|
||||
gis.Equal(expectedErr, err)
|
||||
gis.Empty(sql)
|
||||
gis.Empty(args)
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.Equal(expectedErr, err)
|
||||
gis.Empty(sql)
|
||||
gis.Empty(args)
|
||||
|
||||
ds = dbv2.From("test2").Where(dbv2.Ex{"foo": tc.ds})
|
||||
|
||||
sql, args, err = ds.ToSQL()
|
||||
gis.Equal(expectedErr, err)
|
||||
gis.Empty(sql)
|
||||
gis.Empty(args)
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.Equal(expectedErr, err)
|
||||
gis.Empty(sql)
|
||||
gis.Empty(args)
|
||||
}
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/185
|
||||
func (gis *githubIssuesSuite) TestIssue185() {
|
||||
mDB, sqlMock, err := sqlmock.New()
|
||||
gis.NoError(err)
|
||||
sqlMock.ExpectQuery(
|
||||
`SELECT \* FROM \(SELECT "id" FROM "table" ORDER BY "id" ASC\) AS "t1" UNION
|
||||
\(SELECT \* FROM \(SELECT "id" FROM "table" ORDER BY "id" ASC\) AS "t1"\)`,
|
||||
).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).FromCSVString("1\n2\n3\n4\n"))
|
||||
db := dbv2.New("mock", mDB)
|
||||
|
||||
ds := db.Select("id").From("table").Order(dbv2.C("id").Asc()).
|
||||
Union(
|
||||
db.Select("id").From("table").Order(dbv2.C("id").Asc()),
|
||||
)
|
||||
|
||||
ctx := context.Background()
|
||||
var i []int
|
||||
gis.NoError(ds.ScanValsContext(ctx, &i))
|
||||
gis.Equal([]int{1, 2, 3, 4}, i)
|
||||
}
|
||||
|
||||
// Test for https://github.com/doug-martin/dbv2/issues/203
|
||||
func (gis *githubIssuesSuite) TestIssue203() {
|
||||
// Schema definitions.
|
||||
authSchema := dbv2.S("company_auth")
|
||||
|
||||
// Table definitions
|
||||
usersTable := authSchema.Table("users")
|
||||
|
||||
u := usersTable.As("u")
|
||||
|
||||
ds := dbv2.From(u).Select(
|
||||
u.Col("id"),
|
||||
u.Col("name"),
|
||||
u.Col("created_at"),
|
||||
u.Col("updated_at"),
|
||||
)
|
||||
|
||||
sql, args, err := ds.ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal(`SELECT "u"."id", "u"."name", "u"."created_at", "u"."updated_at" FROM "company_auth"."users" AS "u"`, sql)
|
||||
gis.Empty(args, []interface{}{})
|
||||
|
||||
sql, args, err = ds.Prepared(true).ToSQL()
|
||||
gis.NoError(err)
|
||||
gis.Equal(`SELECT "u"."id", "u"."name", "u"."created_at", "u"."updated_at" FROM "company_auth"."users" AS "u"`, sql)
|
||||
gis.Empty(args, []interface{}{})
|
||||
}
|
||||
|
||||
func (gis *githubIssuesSuite) TestIssue290() {
|
||||
type OcomModel struct {
|
||||
ID uint `json:"id" db:"id" ff:"skipinsert"`
|
||||
CreatedDate time.Time `json:"created_date" db:"created_date" ff:"skipupdate"`
|
||||
ModifiedDate time.Time `json:"modified_date" db:"modified_date"`
|
||||
}
|
||||
|
||||
type ActiveModel struct {
|
||||
OcomModel
|
||||
ActiveStartDate time.Time `json:"active_start_date" db:"active_start_date"`
|
||||
ActiveEndDate *time.Time `json:"active_end_date" db:"active_end_date"`
|
||||
}
|
||||
|
||||
type CodeModel struct {
|
||||
ActiveModel
|
||||
|
||||
Code string `json:"code" db:"code"`
|
||||
Description string `json:"description" binding:"required" db:"description"`
|
||||
}
|
||||
|
||||
type CodeExample struct {
|
||||
CodeModel
|
||||
}
|
||||
|
||||
var item CodeExample
|
||||
item.Code = "Code"
|
||||
item.Description = "Description"
|
||||
item.ID = 1 // Value set HERE!
|
||||
item.CreatedDate = time.Date(
|
||||
2021, 1, 1, 1, 1, 1, 1, time.UTC)
|
||||
item.ModifiedDate = time.Date(
|
||||
2021, 2, 2, 2, 2, 2, 2, time.UTC) // The Value we Get!
|
||||
item.ActiveStartDate = time.Date(
|
||||
2021, 3, 3, 3, 3, 3, 3, time.UTC)
|
||||
|
||||
updateQuery := dbv2.From("example").Update().Set(item).Where(dbv2.C("id").Eq(1))
|
||||
|
||||
sql, params, err := updateQuery.ToSQL()
|
||||
|
||||
gis.NoError(err)
|
||||
gis.Empty(params)
|
||||
gis.Equal(`UPDATE "example" SET "active_end_date"=NULL,"active_start_date"='2021-03-03T03:03:03.000000003Z',"code"='Code',"description"='Description',"id"=1,"modified_date"='2021-02-02T02:02:02.000000002Z' WHERE ("id" = 1)`, sql) //nolint:lll
|
||||
}
|
||||
|
||||
func TestGithubIssuesSuite(t *testing.T) {
|
||||
suite.Run(t, new(githubIssuesSuite))
|
||||
}
|
||||
Reference in New Issue
Block a user