Skip to content

Commit 1fa3d4f

Browse files
Add basic tests for applier (#1165)
* Add basic tests for applier * Add header
1 parent 3c946e9 commit 1fa3d4f

File tree

3 files changed

+181
-9
lines changed

3 files changed

+181
-9
lines changed

go/logic/applier.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package logic
88
import (
99
gosql "database/sql"
1010
"fmt"
11+
"strings"
1112
"sync"
1213
"sync/atomic"
1314
"time"
@@ -122,17 +123,16 @@ func (this *Applier) validateAndReadTimeZone() error {
122123
// - User may skip strict mode
123124
// - User may allow zero dats or zero in dates
124125
func (this *Applier) generateSqlModeQuery() string {
125-
sqlModeAddendum := `,NO_AUTO_VALUE_ON_ZERO`
126+
sqlModeAddendum := []string{`NO_AUTO_VALUE_ON_ZERO`}
126127
if !this.migrationContext.SkipStrictMode {
127-
sqlModeAddendum = fmt.Sprintf("%s,STRICT_ALL_TABLES", sqlModeAddendum)
128+
sqlModeAddendum = append(sqlModeAddendum, `STRICT_ALL_TABLES`)
128129
}
129-
sqlModeQuery := fmt.Sprintf("CONCAT(@@session.sql_mode, ',%s')", sqlModeAddendum)
130+
sqlModeQuery := fmt.Sprintf("CONCAT(@@session.sql_mode, ',%s')", strings.Join(sqlModeAddendum, ","))
130131
if this.migrationContext.AllowZeroInDate {
131132
sqlModeQuery = fmt.Sprintf("REPLACE(REPLACE(%s, 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')", sqlModeQuery)
132133
}
133-
sqlModeQuery = fmt.Sprintf("sql_mode = %s", sqlModeQuery)
134134

135-
return sqlModeQuery
135+
return fmt.Sprintf("sql_mode = %s", sqlModeQuery)
136136
}
137137

138138
// readTableColumns reads table columns on applier

go/logic/applier_test.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*
2+
Copyright 2022 GitHub Inc.
3+
See https://github.com/github/gh-ost/blob/master/LICENSE
4+
*/
5+
6+
package logic
7+
8+
import (
9+
"strings"
10+
"testing"
11+
12+
test "github.com/openark/golib/tests"
13+
14+
"github.com/github/gh-ost/go/base"
15+
"github.com/github/gh-ost/go/binlog"
16+
"github.com/github/gh-ost/go/sql"
17+
)
18+
19+
func TestApplierGenerateSqlModeQuery(t *testing.T) {
20+
migrationContext := base.NewMigrationContext()
21+
applier := NewApplier(migrationContext)
22+
23+
{
24+
test.S(t).ExpectEquals(
25+
applier.generateSqlModeQuery(),
26+
`sql_mode = CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES')`,
27+
)
28+
}
29+
{
30+
migrationContext.SkipStrictMode = true
31+
migrationContext.AllowZeroInDate = false
32+
test.S(t).ExpectEquals(
33+
applier.generateSqlModeQuery(),
34+
`sql_mode = CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO')`,
35+
)
36+
}
37+
{
38+
migrationContext.SkipStrictMode = false
39+
migrationContext.AllowZeroInDate = true
40+
test.S(t).ExpectEquals(
41+
applier.generateSqlModeQuery(),
42+
`sql_mode = REPLACE(REPLACE(CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES'), 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')`,
43+
)
44+
}
45+
{
46+
migrationContext.SkipStrictMode = true
47+
migrationContext.AllowZeroInDate = true
48+
test.S(t).ExpectEquals(
49+
applier.generateSqlModeQuery(),
50+
`sql_mode = REPLACE(REPLACE(CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO'), 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')`,
51+
)
52+
}
53+
}
54+
55+
func TestApplierUpdateModifiesUniqueKeyColumns(t *testing.T) {
56+
columns := sql.NewColumnList([]string{"id", "item_id"})
57+
columnValues := sql.ToColumnValues([]interface{}{123456, 42})
58+
59+
migrationContext := base.NewMigrationContext()
60+
migrationContext.OriginalTableColumns = columns
61+
migrationContext.UniqueKey = &sql.UniqueKey{
62+
Name: t.Name(),
63+
Columns: *columns,
64+
}
65+
66+
applier := NewApplier(migrationContext)
67+
68+
t.Run("unmodified", func(t *testing.T) {
69+
modifiedColumn, isModified := applier.updateModifiesUniqueKeyColumns(&binlog.BinlogDMLEvent{
70+
DatabaseName: "test",
71+
DML: binlog.UpdateDML,
72+
NewColumnValues: columnValues,
73+
WhereColumnValues: columnValues,
74+
})
75+
test.S(t).ExpectEquals(modifiedColumn, "")
76+
test.S(t).ExpectFalse(isModified)
77+
})
78+
79+
t.Run("modified", func(t *testing.T) {
80+
modifiedColumn, isModified := applier.updateModifiesUniqueKeyColumns(&binlog.BinlogDMLEvent{
81+
DatabaseName: "test",
82+
DML: binlog.UpdateDML,
83+
NewColumnValues: sql.ToColumnValues([]interface{}{123456, 24}),
84+
WhereColumnValues: columnValues,
85+
})
86+
test.S(t).ExpectEquals(modifiedColumn, "item_id")
87+
test.S(t).ExpectTrue(isModified)
88+
})
89+
}
90+
91+
func TestApplierBuildDMLEventQuery(t *testing.T) {
92+
columns := sql.NewColumnList([]string{"id", "item_id"})
93+
columnValues := sql.ToColumnValues([]interface{}{123456, 42})
94+
95+
migrationContext := base.NewMigrationContext()
96+
migrationContext.OriginalTableName = "test"
97+
migrationContext.OriginalTableColumns = columns
98+
migrationContext.SharedColumns = columns
99+
migrationContext.MappedSharedColumns = columns
100+
migrationContext.UniqueKey = &sql.UniqueKey{
101+
Name: t.Name(),
102+
Columns: *columns,
103+
}
104+
105+
applier := NewApplier(migrationContext)
106+
107+
t.Run("delete", func(t *testing.T) {
108+
binlogEvent := &binlog.BinlogDMLEvent{
109+
DatabaseName: "test",
110+
DML: binlog.DeleteDML,
111+
WhereColumnValues: columnValues,
112+
}
113+
114+
res := applier.buildDMLEventQuery(binlogEvent)
115+
test.S(t).ExpectEquals(len(res), 1)
116+
test.S(t).ExpectNil(res[0].err)
117+
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
118+
`delete /* gh-ost `+"`test`.`_test_gho`"+` */
119+
from
120+
`+"`test`.`_test_gho`"+`
121+
where
122+
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
123+
124+
test.S(t).ExpectEquals(len(res[0].args), 2)
125+
test.S(t).ExpectEquals(res[0].args[0], 123456)
126+
test.S(t).ExpectEquals(res[0].args[1], 42)
127+
})
128+
129+
t.Run("insert", func(t *testing.T) {
130+
binlogEvent := &binlog.BinlogDMLEvent{
131+
DatabaseName: "test",
132+
DML: binlog.InsertDML,
133+
NewColumnValues: columnValues,
134+
}
135+
res := applier.buildDMLEventQuery(binlogEvent)
136+
test.S(t).ExpectEquals(len(res), 1)
137+
test.S(t).ExpectNil(res[0].err)
138+
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
139+
`replace /* gh-ost `+"`test`.`_test_gho`"+` */ into
140+
`+"`test`.`_test_gho`"+`
141+
`+"(`id`, `item_id`)"+`
142+
values
143+
(?, ?)`)
144+
test.S(t).ExpectEquals(len(res[0].args), 2)
145+
test.S(t).ExpectEquals(res[0].args[0], 123456)
146+
test.S(t).ExpectEquals(res[0].args[1], 42)
147+
})
148+
149+
t.Run("update", func(t *testing.T) {
150+
binlogEvent := &binlog.BinlogDMLEvent{
151+
DatabaseName: "test",
152+
DML: binlog.UpdateDML,
153+
NewColumnValues: columnValues,
154+
WhereColumnValues: columnValues,
155+
}
156+
res := applier.buildDMLEventQuery(binlogEvent)
157+
test.S(t).ExpectEquals(len(res), 1)
158+
test.S(t).ExpectNil(res[0].err)
159+
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
160+
`update /* gh-ost `+"`test`.`_test_gho`"+` */
161+
`+"`test`.`_test_gho`"+`
162+
set
163+
`+"`id`"+`=?, `+"`item_id`"+`=?
164+
where
165+
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
166+
test.S(t).ExpectEquals(len(res[0].args), 4)
167+
test.S(t).ExpectEquals(res[0].args[0], 123456)
168+
test.S(t).ExpectEquals(res[0].args[1], 42)
169+
test.S(t).ExpectEquals(res[0].args[2], 123456)
170+
test.S(t).ExpectEquals(res[0].args[3], 42)
171+
})
172+
}

go/sql/builder.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,13 @@ func BuildDMLUpdateQuery(databaseName, tableName string, tableColumns, sharedCol
505505
return "", sharedArgs, uniqueKeyArgs, err
506506
}
507507
result = fmt.Sprintf(`
508-
update /* gh-ost %s.%s */
509-
%s.%s
508+
update /* gh-ost %s.%s */
509+
%s.%s
510510
set
511511
%s
512512
where
513-
%s
514-
`, databaseName, tableName,
513+
%s
514+
`, databaseName, tableName,
515515
databaseName, tableName,
516516
setClause,
517517
equalsComparison,

0 commit comments

Comments
 (0)