Add basic tests for applier (#1165)
* Add basic tests for applier * Add header
This commit is contained in:
parent
3c946e97d7
commit
1fa3d4f75a
@ -8,6 +8,7 @@ package logic
|
|||||||
import (
|
import (
|
||||||
gosql "database/sql"
|
gosql "database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -122,17 +123,16 @@ func (this *Applier) validateAndReadTimeZone() error {
|
|||||||
// - User may skip strict mode
|
// - User may skip strict mode
|
||||||
// - User may allow zero dats or zero in dates
|
// - User may allow zero dats or zero in dates
|
||||||
func (this *Applier) generateSqlModeQuery() string {
|
func (this *Applier) generateSqlModeQuery() string {
|
||||||
sqlModeAddendum := `,NO_AUTO_VALUE_ON_ZERO`
|
sqlModeAddendum := []string{`NO_AUTO_VALUE_ON_ZERO`}
|
||||||
if !this.migrationContext.SkipStrictMode {
|
if !this.migrationContext.SkipStrictMode {
|
||||||
sqlModeAddendum = fmt.Sprintf("%s,STRICT_ALL_TABLES", sqlModeAddendum)
|
sqlModeAddendum = append(sqlModeAddendum, `STRICT_ALL_TABLES`)
|
||||||
}
|
}
|
||||||
sqlModeQuery := fmt.Sprintf("CONCAT(@@session.sql_mode, ',%s')", sqlModeAddendum)
|
sqlModeQuery := fmt.Sprintf("CONCAT(@@session.sql_mode, ',%s')", strings.Join(sqlModeAddendum, ","))
|
||||||
if this.migrationContext.AllowZeroInDate {
|
if this.migrationContext.AllowZeroInDate {
|
||||||
sqlModeQuery = fmt.Sprintf("REPLACE(REPLACE(%s, 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')", sqlModeQuery)
|
sqlModeQuery = fmt.Sprintf("REPLACE(REPLACE(%s, 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')", sqlModeQuery)
|
||||||
}
|
}
|
||||||
sqlModeQuery = fmt.Sprintf("sql_mode = %s", sqlModeQuery)
|
|
||||||
|
|
||||||
return sqlModeQuery
|
return fmt.Sprintf("sql_mode = %s", sqlModeQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
// readTableColumns reads table columns on applier
|
// readTableColumns reads table columns on applier
|
||||||
|
172
go/logic/applier_test.go
Normal file
172
go/logic/applier_test.go
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 GitHub Inc.
|
||||||
|
See https://github.com/github/gh-ost/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
test "github.com/openark/golib/tests"
|
||||||
|
|
||||||
|
"github.com/github/gh-ost/go/base"
|
||||||
|
"github.com/github/gh-ost/go/binlog"
|
||||||
|
"github.com/github/gh-ost/go/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestApplierGenerateSqlModeQuery(t *testing.T) {
|
||||||
|
migrationContext := base.NewMigrationContext()
|
||||||
|
applier := NewApplier(migrationContext)
|
||||||
|
|
||||||
|
{
|
||||||
|
test.S(t).ExpectEquals(
|
||||||
|
applier.generateSqlModeQuery(),
|
||||||
|
`sql_mode = CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES')`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
migrationContext.SkipStrictMode = true
|
||||||
|
migrationContext.AllowZeroInDate = false
|
||||||
|
test.S(t).ExpectEquals(
|
||||||
|
applier.generateSqlModeQuery(),
|
||||||
|
`sql_mode = CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO')`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
migrationContext.SkipStrictMode = false
|
||||||
|
migrationContext.AllowZeroInDate = true
|
||||||
|
test.S(t).ExpectEquals(
|
||||||
|
applier.generateSqlModeQuery(),
|
||||||
|
`sql_mode = REPLACE(REPLACE(CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES'), 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
migrationContext.SkipStrictMode = true
|
||||||
|
migrationContext.AllowZeroInDate = true
|
||||||
|
test.S(t).ExpectEquals(
|
||||||
|
applier.generateSqlModeQuery(),
|
||||||
|
`sql_mode = REPLACE(REPLACE(CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO'), 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplierUpdateModifiesUniqueKeyColumns(t *testing.T) {
|
||||||
|
columns := sql.NewColumnList([]string{"id", "item_id"})
|
||||||
|
columnValues := sql.ToColumnValues([]interface{}{123456, 42})
|
||||||
|
|
||||||
|
migrationContext := base.NewMigrationContext()
|
||||||
|
migrationContext.OriginalTableColumns = columns
|
||||||
|
migrationContext.UniqueKey = &sql.UniqueKey{
|
||||||
|
Name: t.Name(),
|
||||||
|
Columns: *columns,
|
||||||
|
}
|
||||||
|
|
||||||
|
applier := NewApplier(migrationContext)
|
||||||
|
|
||||||
|
t.Run("unmodified", func(t *testing.T) {
|
||||||
|
modifiedColumn, isModified := applier.updateModifiesUniqueKeyColumns(&binlog.BinlogDMLEvent{
|
||||||
|
DatabaseName: "test",
|
||||||
|
DML: binlog.UpdateDML,
|
||||||
|
NewColumnValues: columnValues,
|
||||||
|
WhereColumnValues: columnValues,
|
||||||
|
})
|
||||||
|
test.S(t).ExpectEquals(modifiedColumn, "")
|
||||||
|
test.S(t).ExpectFalse(isModified)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("modified", func(t *testing.T) {
|
||||||
|
modifiedColumn, isModified := applier.updateModifiesUniqueKeyColumns(&binlog.BinlogDMLEvent{
|
||||||
|
DatabaseName: "test",
|
||||||
|
DML: binlog.UpdateDML,
|
||||||
|
NewColumnValues: sql.ToColumnValues([]interface{}{123456, 24}),
|
||||||
|
WhereColumnValues: columnValues,
|
||||||
|
})
|
||||||
|
test.S(t).ExpectEquals(modifiedColumn, "item_id")
|
||||||
|
test.S(t).ExpectTrue(isModified)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplierBuildDMLEventQuery(t *testing.T) {
|
||||||
|
columns := sql.NewColumnList([]string{"id", "item_id"})
|
||||||
|
columnValues := sql.ToColumnValues([]interface{}{123456, 42})
|
||||||
|
|
||||||
|
migrationContext := base.NewMigrationContext()
|
||||||
|
migrationContext.OriginalTableName = "test"
|
||||||
|
migrationContext.OriginalTableColumns = columns
|
||||||
|
migrationContext.SharedColumns = columns
|
||||||
|
migrationContext.MappedSharedColumns = columns
|
||||||
|
migrationContext.UniqueKey = &sql.UniqueKey{
|
||||||
|
Name: t.Name(),
|
||||||
|
Columns: *columns,
|
||||||
|
}
|
||||||
|
|
||||||
|
applier := NewApplier(migrationContext)
|
||||||
|
|
||||||
|
t.Run("delete", func(t *testing.T) {
|
||||||
|
binlogEvent := &binlog.BinlogDMLEvent{
|
||||||
|
DatabaseName: "test",
|
||||||
|
DML: binlog.DeleteDML,
|
||||||
|
WhereColumnValues: columnValues,
|
||||||
|
}
|
||||||
|
|
||||||
|
res := applier.buildDMLEventQuery(binlogEvent)
|
||||||
|
test.S(t).ExpectEquals(len(res), 1)
|
||||||
|
test.S(t).ExpectNil(res[0].err)
|
||||||
|
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
|
||||||
|
`delete /* gh-ost `+"`test`.`_test_gho`"+` */
|
||||||
|
from
|
||||||
|
`+"`test`.`_test_gho`"+`
|
||||||
|
where
|
||||||
|
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
|
||||||
|
|
||||||
|
test.S(t).ExpectEquals(len(res[0].args), 2)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[0], 123456)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[1], 42)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("insert", func(t *testing.T) {
|
||||||
|
binlogEvent := &binlog.BinlogDMLEvent{
|
||||||
|
DatabaseName: "test",
|
||||||
|
DML: binlog.InsertDML,
|
||||||
|
NewColumnValues: columnValues,
|
||||||
|
}
|
||||||
|
res := applier.buildDMLEventQuery(binlogEvent)
|
||||||
|
test.S(t).ExpectEquals(len(res), 1)
|
||||||
|
test.S(t).ExpectNil(res[0].err)
|
||||||
|
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
|
||||||
|
`replace /* gh-ost `+"`test`.`_test_gho`"+` */ into
|
||||||
|
`+"`test`.`_test_gho`"+`
|
||||||
|
`+"(`id`, `item_id`)"+`
|
||||||
|
values
|
||||||
|
(?, ?)`)
|
||||||
|
test.S(t).ExpectEquals(len(res[0].args), 2)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[0], 123456)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[1], 42)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("update", func(t *testing.T) {
|
||||||
|
binlogEvent := &binlog.BinlogDMLEvent{
|
||||||
|
DatabaseName: "test",
|
||||||
|
DML: binlog.UpdateDML,
|
||||||
|
NewColumnValues: columnValues,
|
||||||
|
WhereColumnValues: columnValues,
|
||||||
|
}
|
||||||
|
res := applier.buildDMLEventQuery(binlogEvent)
|
||||||
|
test.S(t).ExpectEquals(len(res), 1)
|
||||||
|
test.S(t).ExpectNil(res[0].err)
|
||||||
|
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
|
||||||
|
`update /* gh-ost `+"`test`.`_test_gho`"+` */
|
||||||
|
`+"`test`.`_test_gho`"+`
|
||||||
|
set
|
||||||
|
`+"`id`"+`=?, `+"`item_id`"+`=?
|
||||||
|
where
|
||||||
|
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
|
||||||
|
test.S(t).ExpectEquals(len(res[0].args), 4)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[0], 123456)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[1], 42)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[2], 123456)
|
||||||
|
test.S(t).ExpectEquals(res[0].args[3], 42)
|
||||||
|
})
|
||||||
|
}
|
@ -505,13 +505,13 @@ func BuildDMLUpdateQuery(databaseName, tableName string, tableColumns, sharedCol
|
|||||||
return "", sharedArgs, uniqueKeyArgs, err
|
return "", sharedArgs, uniqueKeyArgs, err
|
||||||
}
|
}
|
||||||
result = fmt.Sprintf(`
|
result = fmt.Sprintf(`
|
||||||
update /* gh-ost %s.%s */
|
update /* gh-ost %s.%s */
|
||||||
%s.%s
|
%s.%s
|
||||||
set
|
set
|
||||||
%s
|
%s
|
||||||
where
|
where
|
||||||
%s
|
%s
|
||||||
`, databaseName, tableName,
|
`, databaseName, tableName,
|
||||||
databaseName, tableName,
|
databaseName, tableName,
|
||||||
setClause,
|
setClause,
|
||||||
equalsComparison,
|
equalsComparison,
|
||||||
|
Loading…
Reference in New Issue
Block a user