Skip to content

Commit b3f5c0f

Browse files
authored
dump: support unescape string (go-mysql-org#104)
1 parent 895183d commit b3f5c0f

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

cmd/go-canal/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ var tableDB = flag.String("table_db", "test", "database for dump tables")
2929
var ignoreTables = flag.String("ignore_tables", "", "ignore tables, must be database.table format, separated by comma")
3030

3131
func main() {
32+
flag.Parse()
33+
3234
cfg := canal.NewDefaultConfig()
3335
cfg.Addr = fmt.Sprintf("%s:%d", *host, *port)
3436
cfg.User = *user

dump/dump_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func (s *schemaTestSuite) TestParseValue(c *C) {
139139
str := `'abc\\',''`
140140
values, err := parseValues(str)
141141
c.Assert(err, IsNil)
142-
c.Assert(values, DeepEquals, []string{`'abc\\'`, `''`})
142+
c.Assert(values, DeepEquals, []string{`'abc\'`, `''`})
143143

144144
str = `123,'\Z#÷QÎx£. Æ‘ÇoPâÅ_\r—\\','','qn'`
145145
values, err = parseValues(str)

dump/parser.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ func parseValues(str string) ([]string, error) {
109109
// read string until another single quote
110110
j := i + 1
111111

112+
escaped := false
112113
for j < len(str) {
113114
if str[j] == '\\' {
114115
// skip escaped character
115116
j += 2
117+
escaped = true
116118
continue
117119
} else if str[j] == '\'' {
118120
break
@@ -125,7 +127,11 @@ func parseValues(str string) ([]string, error) {
125127
return nil, fmt.Errorf("parse quote values error")
126128
}
127129

128-
values = append(values, str[i:j+1])
130+
value := str[i : j+1]
131+
if escaped {
132+
value = unescapeString(value)
133+
}
134+
values = append(values, value)
129135
// skip ' and ,
130136
i = j + 2
131137
}
@@ -135,3 +141,48 @@ func parseValues(str string) ([]string, error) {
135141

136142
return values, nil
137143
}
144+
145+
// unescapeString un-escapes the string.
146+
// mysqldump will escape the string when dumps,
147+
// Refer http://dev.mysql.com/doc/refman/5.7/en/string-literals.html
148+
func unescapeString(s string) string {
149+
i := 0
150+
151+
value := make([]byte, 0, len(s))
152+
for i < len(s) {
153+
if s[i] == '\\' {
154+
j := i + 1
155+
if j == len(s) {
156+
// The last char is \, remove
157+
break
158+
}
159+
160+
value = append(value, unescapeChar(s[j]))
161+
i += 2
162+
} else {
163+
value = append(value, s[i])
164+
i++
165+
}
166+
}
167+
168+
return string(value)
169+
}
170+
171+
func unescapeChar(ch byte) byte {
172+
// \" \' \\ \n \0 \b \Z \r \t ==> escape to one char
173+
switch ch {
174+
case 'n':
175+
ch = '\n'
176+
case '0':
177+
ch = 0
178+
case 'b':
179+
ch = 8
180+
case 'Z':
181+
ch = 26
182+
case 'r':
183+
ch = '\r'
184+
case 't':
185+
ch = '\t'
186+
}
187+
return ch
188+
}

0 commit comments

Comments
 (0)