|
@@ -807,12 +807,12 @@ func appendLengthEncodedInteger(b []byte, n uint64) []byte {
|
|
|
byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
|
|
byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Escape string with backslashes (\)
|
|
|
|
|
|
|
+// escapeBytesBackslash escapes []byte with backslashes (\)
|
|
|
// This escapes the contents of a string (provided as []byte) by adding backslashes before special
|
|
// This escapes the contents of a string (provided as []byte) by adding backslashes before special
|
|
|
// characters, and turning others into specific escape sequences, such as
|
|
// characters, and turning others into specific escape sequences, such as
|
|
|
// turning newlines into \n and null bytes into \0.
|
|
// turning newlines into \n and null bytes into \0.
|
|
|
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L823-L932
|
|
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L823-L932
|
|
|
-func escapeBackslash(buf, v []byte) []byte {
|
|
|
|
|
|
|
+func escapeBytesBackslash(buf, v []byte) []byte {
|
|
|
pos := len(buf)
|
|
pos := len(buf)
|
|
|
end := pos + len(v)*2
|
|
end := pos + len(v)*2
|
|
|
if cap(buf) < end {
|
|
if cap(buf) < end {
|
|
@@ -861,12 +861,63 @@ func escapeBackslash(buf, v []byte) []byte {
|
|
|
return buf[:pos]
|
|
return buf[:pos]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Escape apostrophes by doubling them up
|
|
|
|
|
|
|
+// escapeStringBackslash is similar to escapeBytesBackslash but for string.
|
|
|
|
|
+func escapeStringBackslash(buf []byte, v string) []byte {
|
|
|
|
|
+ pos := len(buf)
|
|
|
|
|
+ end := pos + len(v)*2
|
|
|
|
|
+ if cap(buf) < end {
|
|
|
|
|
+ n := make([]byte, pos+end)
|
|
|
|
|
+ copy(n, buf)
|
|
|
|
|
+ buf = n
|
|
|
|
|
+ }
|
|
|
|
|
+ buf = buf[0:end]
|
|
|
|
|
+
|
|
|
|
|
+ for i := 0; i < len(v); i++ {
|
|
|
|
|
+ c := v[i]
|
|
|
|
|
+ switch c {
|
|
|
|
|
+ case '\x00':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = '0'
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ case '\n':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = 'n'
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ case '\r':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = 'r'
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ case '\x1a':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = 'Z'
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ case '\'':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = '\''
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ case '"':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = '"'
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ case '\\':
|
|
|
|
|
+ buf[pos] = '\\'
|
|
|
|
|
+ buf[pos+1] = '\\'
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ default:
|
|
|
|
|
+ buf[pos] = c
|
|
|
|
|
+ pos += 1
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return buf[:pos]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// escapeBytesQuotes escapes apostrophes in []byte by doubling them up.
|
|
|
// This escapes the contents of a string by doubling up any apostrophes that
|
|
// This escapes the contents of a string by doubling up any apostrophes that
|
|
|
// it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
|
|
// it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
|
|
|
// effect on the server.
|
|
// effect on the server.
|
|
|
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L963-L1038
|
|
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L963-L1038
|
|
|
-func escapeQuotes(buf, v []byte) []byte {
|
|
|
|
|
|
|
+func escapeBytesQuotes(buf, v []byte) []byte {
|
|
|
pos := len(buf)
|
|
pos := len(buf)
|
|
|
end := pos + len(v)*2
|
|
end := pos + len(v)*2
|
|
|
if cap(buf) < end {
|
|
if cap(buf) < end {
|
|
@@ -889,3 +940,29 @@ func escapeQuotes(buf, v []byte) []byte {
|
|
|
|
|
|
|
|
return buf[:pos]
|
|
return buf[:pos]
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+// escapeStringQuotes is similar to escapeBytesQuotes but for string.
|
|
|
|
|
+func escapeStringQuotes(buf []byte, v string) []byte {
|
|
|
|
|
+ pos := len(buf)
|
|
|
|
|
+ end := pos + len(v)*2
|
|
|
|
|
+ if cap(buf) < end {
|
|
|
|
|
+ n := make([]byte, pos+end)
|
|
|
|
|
+ copy(n, buf)
|
|
|
|
|
+ buf = n
|
|
|
|
|
+ }
|
|
|
|
|
+ buf = buf[0:end]
|
|
|
|
|
+
|
|
|
|
|
+ for i := 0; i < len(v); i++ {
|
|
|
|
|
+ c := v[i]
|
|
|
|
|
+ if c == '\'' {
|
|
|
|
|
+ buf[pos] = '\''
|
|
|
|
|
+ buf[pos+1] = '\''
|
|
|
|
|
+ pos += 2
|
|
|
|
|
+ } else {
|
|
|
|
|
+ buf[pos] = c
|
|
|
|
|
+ pos++
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return buf[:pos]
|
|
|
|
|
+}
|