fork github.com/doug-martin
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
package sqlgen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/db/v2/exp"
|
||||
"git.fsdpf.net/go/db/v2/internal/sb"
|
||||
"git.fsdpf.net/go/db/v2/sqlgen"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type (
|
||||
updateTestCase struct {
|
||||
clause exp.UpdateClauses
|
||||
sql string
|
||||
isPrepared bool
|
||||
args []interface{}
|
||||
err string
|
||||
}
|
||||
updateSQLGeneratorSuite struct {
|
||||
baseSQLGeneratorSuite
|
||||
}
|
||||
)
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) assertCases(usg sqlgen.UpdateSQLGenerator, testCases ...updateTestCase) {
|
||||
for _, tc := range testCases {
|
||||
b := sb.NewSQLBuilder(tc.isPrepared)
|
||||
usg.Generate(b, tc.clause)
|
||||
switch {
|
||||
case len(tc.err) > 0:
|
||||
usgs.assertErrorSQL(b, tc.err)
|
||||
case tc.isPrepared:
|
||||
usgs.assertPreparedSQL(b, tc.sql, tc.args)
|
||||
default:
|
||||
usgs.assertNotPreparedSQL(b, tc.sql)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestDialect() {
|
||||
opts := sqlgen.DefaultDialectOptions()
|
||||
d := sqlgen.NewUpdateSQLGenerator("test", opts)
|
||||
usgs.Equal("test", d.Dialect())
|
||||
|
||||
opts2 := sqlgen.DefaultDialectOptions()
|
||||
d2 := sqlgen.NewUpdateSQLGenerator("test2", opts2)
|
||||
usgs.Equal("test2", d2.Dialect())
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_unsupportedFragment() {
|
||||
opts := sqlgen.DefaultDialectOptions()
|
||||
opts.UpdateSQLOrder = []sqlgen.SQLFragmentType{sqlgen.InsertBeingSQLFragment}
|
||||
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", "")).
|
||||
SetSetValues(exp.Record{"a": "b", "b": "c"})
|
||||
expectedErr := "db: unsupported UPDATE SQL fragment InsertBeingSQLFragment"
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, err: expectedErr},
|
||||
updateTestCase{clause: uc, err: expectedErr, isPrepared: true},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_empty() {
|
||||
uc := exp.NewUpdateClauses()
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", sqlgen.DefaultDialectOptions()),
|
||||
updateTestCase{clause: uc, err: sqlgen.ErrNoSourceForUpdate.Error()},
|
||||
updateTestCase{clause: uc, err: sqlgen.ErrNoSourceForUpdate.Error(), isPrepared: true},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_withBadUpdateValues() {
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", "")).
|
||||
SetSetValues(true)
|
||||
|
||||
expectedErr := "db: unsupported update interface type bool"
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", sqlgen.DefaultDialectOptions()),
|
||||
updateTestCase{clause: uc, err: expectedErr},
|
||||
updateTestCase{clause: uc, err: expectedErr, isPrepared: true},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_noSetValues() {
|
||||
uc := exp.NewUpdateClauses().SetTable(exp.NewIdentifierExpression("", "test", ""))
|
||||
|
||||
expectedErr := sqlgen.ErrNoSetValuesForUpdate.Error()
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", sqlgen.DefaultDialectOptions()),
|
||||
updateTestCase{clause: uc, err: expectedErr},
|
||||
updateTestCase{clause: uc, err: expectedErr, isPrepared: true},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_withFrom() {
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", "")).
|
||||
SetSetValues(exp.Record{"foo": "bar"}).
|
||||
SetFrom(exp.NewColumnListExpression("other_test"))
|
||||
|
||||
ucNullSet := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", "")).
|
||||
SetSetValues(exp.Record{"foo": nil}).
|
||||
SetFrom(exp.NewColumnListExpression("other_test"))
|
||||
|
||||
opts := sqlgen.DefaultDialectOptions()
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "foo"='bar' FROM "other_test"`},
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "foo"=? FROM "other_test"`, isPrepared: true, args: []interface{}{"bar"}},
|
||||
|
||||
updateTestCase{clause: ucNullSet, sql: `UPDATE "test" SET "foo"=NULL FROM "other_test"`},
|
||||
updateTestCase{clause: ucNullSet, sql: `UPDATE "test" SET "foo"=? FROM "other_test"`, isPrepared: true, args: []interface{}{nil}},
|
||||
)
|
||||
|
||||
opts = sqlgen.DefaultDialectOptions()
|
||||
opts.UseFromClauseForMultipleUpdateTables = false
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test","other_test" SET "foo"='bar'`},
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test","other_test" SET "foo"=?`, isPrepared: true, args: []interface{}{"bar"}},
|
||||
|
||||
updateTestCase{clause: ucNullSet, sql: `UPDATE "test","other_test" SET "foo"=NULL`},
|
||||
updateTestCase{clause: ucNullSet, sql: `UPDATE "test","other_test" SET "foo"=?`, isPrepared: true, args: []interface{}{nil}},
|
||||
)
|
||||
|
||||
opts = sqlgen.DefaultDialectOptions()
|
||||
opts.SupportsMultipleUpdateTables = false
|
||||
expectedErr := "db: test dialect does not support multiple tables in UPDATE"
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, err: expectedErr},
|
||||
updateTestCase{clause: uc, err: expectedErr, isPrepared: true},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_withUpdateExpression() {
|
||||
opts := sqlgen.DefaultDialectOptions()
|
||||
// make sure the fragments are used
|
||||
opts.SetFragment = []byte(" set ")
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", ""))
|
||||
ucRecord := uc.SetSetValues(exp.Record{"a": "b", "b": "c"})
|
||||
ucRecordNullVal := uc.SetSetValues(exp.Record{"a": "b", "b": nil})
|
||||
ucRecordBoolVals := uc.SetSetValues(exp.Record{"a": true, "b": false})
|
||||
ucEmptyRecord := uc.SetSetValues(exp.Record{})
|
||||
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: ucRecord, sql: `UPDATE "test" set "a"='b',"b"='c'`},
|
||||
updateTestCase{clause: ucRecord, sql: `UPDATE "test" set "a"=?,"b"=?`, isPrepared: true, args: []interface{}{"b", "c"}},
|
||||
|
||||
updateTestCase{clause: ucRecordNullVal, sql: `UPDATE "test" set "a"='b',"b"=NULL`},
|
||||
updateTestCase{clause: ucRecordNullVal, sql: `UPDATE "test" set "a"=?,"b"=?`, isPrepared: true, args: []interface{}{"b", nil}},
|
||||
|
||||
updateTestCase{clause: ucRecordBoolVals, sql: `UPDATE "test" set "a"=TRUE,"b"=FALSE`},
|
||||
updateTestCase{clause: ucRecordBoolVals, sql: `UPDATE "test" set "a"=?,"b"=?`, isPrepared: true, args: []interface{}{true, false}},
|
||||
|
||||
updateTestCase{clause: ucEmptyRecord, err: sqlgen.ErrNoUpdatedValuesProvided.Error()},
|
||||
updateTestCase{clause: ucEmptyRecord, err: sqlgen.ErrNoUpdatedValuesProvided.Error(), isPrepared: true},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_withOrder() {
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", "")).
|
||||
SetSetValues(exp.Record{"a": "b", "b": "c"}).
|
||||
SetOrder(
|
||||
exp.NewIdentifierExpression("", "", "a").Asc(),
|
||||
exp.NewIdentifierExpression("", "", "b").Desc(),
|
||||
)
|
||||
|
||||
opts := sqlgen.DefaultDialectOptions()
|
||||
opts.SupportsOrderByOnUpdate = true
|
||||
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"='b',"b"='c' ORDER BY "a" ASC, "b" DESC`},
|
||||
updateTestCase{
|
||||
clause: uc,
|
||||
sql: `UPDATE "test" SET "a"=?,"b"=? ORDER BY "a" ASC, "b" DESC`,
|
||||
isPrepared: true,
|
||||
args: []interface{}{"b", "c"},
|
||||
},
|
||||
)
|
||||
|
||||
opts = sqlgen.DefaultDialectOptions()
|
||||
opts.SupportsOrderByOnUpdate = false
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"='b',"b"='c'`},
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"=?,"b"=?`, isPrepared: true, args: []interface{}{"b", "c"}},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_withLimit() {
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test", "")).
|
||||
SetSetValues(exp.Record{"a": "b", "b": "c"}).
|
||||
SetLimit(10)
|
||||
|
||||
opts := sqlgen.DefaultDialectOptions()
|
||||
opts.SupportsLimitOnUpdate = true
|
||||
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"='b',"b"='c' LIMIT 10`},
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"=?,"b"=? LIMIT ?`, isPrepared: true, args: []interface{}{"b", "c", int64(10)}},
|
||||
)
|
||||
|
||||
opts = sqlgen.DefaultDialectOptions()
|
||||
opts.SupportsLimitOnUpdate = false
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", opts),
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"='b',"b"='c'`},
|
||||
updateTestCase{clause: uc, sql: `UPDATE "test" SET "a"=?,"b"=?`, isPrepared: true, args: []interface{}{"b", "c"}},
|
||||
)
|
||||
}
|
||||
|
||||
func (usgs *updateSQLGeneratorSuite) TestGenerate_withCommonTables() {
|
||||
tse := newTestAppendableExpression("select * from foo", emptyArgs, nil, nil)
|
||||
uc := exp.NewUpdateClauses().
|
||||
SetTable(exp.NewIdentifierExpression("", "test_cte", "")).
|
||||
SetSetValues(exp.Record{"a": "b", "b": "c"})
|
||||
ucCte1 := uc.CommonTablesAppend(exp.NewCommonTableExpression(false, "test_cte", tse))
|
||||
ucCte2 := uc.CommonTablesAppend(exp.NewCommonTableExpression(true, "test_cte", tse))
|
||||
|
||||
usgs.assertCases(
|
||||
sqlgen.NewUpdateSQLGenerator("test", sqlgen.DefaultDialectOptions()),
|
||||
updateTestCase{
|
||||
clause: ucCte1,
|
||||
sql: `WITH test_cte AS (select * from foo) UPDATE "test_cte" SET "a"='b',"b"='c'`,
|
||||
},
|
||||
updateTestCase{
|
||||
clause: ucCte1,
|
||||
sql: `WITH test_cte AS (select * from foo) UPDATE "test_cte" SET "a"=?,"b"=?`,
|
||||
isPrepared: true,
|
||||
args: []interface{}{"b", "c"},
|
||||
},
|
||||
|
||||
updateTestCase{
|
||||
clause: ucCte2,
|
||||
sql: `WITH RECURSIVE test_cte AS (select * from foo) UPDATE "test_cte" SET "a"='b',"b"='c'`,
|
||||
},
|
||||
updateTestCase{
|
||||
clause: ucCte2,
|
||||
sql: `WITH RECURSIVE test_cte AS (select * from foo) UPDATE "test_cte" SET "a"=?,"b"=?`,
|
||||
isPrepared: true,
|
||||
args: []interface{}{"b", "c"},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestUpdateSQLGenerator(t *testing.T) {
|
||||
suite.Run(t, new(updateSQLGeneratorSuite))
|
||||
}
|
||||
Reference in New Issue
Block a user