diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 7394c5efa98d6..596422d0b5621 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -136,7 +136,7 @@ func (s *testSuite) TestBindParse(c *C) { c.Check(bindData.UpdateTime, NotNil) // Test fields with quotes or slashes. - sql = `CREATE GLOBAL BINDING FOR select * from t where a BETWEEN "a" and "b" USING select * from t use index(idx) where a BETWEEN "a\nb\rc\td\0e" and "x"` + sql = `CREATE GLOBAL BINDING FOR select * from t where a BETWEEN "a" and "b" USING select * from t use index(idx) where a BETWEEN "a\nb\rc\td\0e" and 'x'` tk.MustExec(sql) tk.MustExec(`DROP global binding for select * from t use index(idx) where a BETWEEN "a\nb\rc\td\0e" and "x"`) } diff --git a/bindinfo/handle.go b/bindinfo/handle.go index b6978dcf7d5db..739a29726b400 100644 --- a/bindinfo/handle.go +++ b/bindinfo/handle.go @@ -24,6 +24,7 @@ import ( "github.com/pingcap/parser" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/store/tikv/oracle" @@ -418,29 +419,29 @@ func (m *BindMeta) isSame(other *BindMeta) bool { func (h *BindHandle) deleteBindInfoSQL(normdOrigSQL, db string) string { return fmt.Sprintf( - "DELETE FROM mysql.bind_info WHERE original_sql='%s' AND default_db='%s'", - normdOrigSQL, - db, + `DELETE FROM mysql.bind_info WHERE original_sql=%s AND default_db=%s`, + expression.Quote(normdOrigSQL), + expression.Quote(db), ) } func (h *BindHandle) insertBindInfoSQL(record *BindRecord) string { - return fmt.Sprintf(`INSERT INTO mysql.bind_info VALUES ('%s', '%s', '%s', '%s', '%s', '%s','%s', '%s')`, - record.OriginalSQL, - record.BindSQL, - record.Db, - record.Status, - record.CreateTime, - record.UpdateTime, - record.Charset, - record.Collation, + return fmt.Sprintf(`INSERT INTO mysql.bind_info VALUES (%s, %s, %s, %s, %s, %s,%s, %s)`, + expression.Quote(record.OriginalSQL), + expression.Quote(record.BindSQL), + expression.Quote(record.Db), + expression.Quote(record.Status), + expression.Quote(record.CreateTime.String()), + expression.Quote(record.UpdateTime.String()), + expression.Quote(record.Charset), + expression.Quote(record.Collation), ) } func (h *BindHandle) logicalDeleteBindInfoSQL(normdOrigSQL, db string, updateTs types.Time) string { - return fmt.Sprintf(`UPDATE mysql.bind_info SET status='%s',update_time='%s' WHERE original_sql='%s' and default_db='%s'`, - deleted, - updateTs, - normdOrigSQL, - db) + return fmt.Sprintf(`UPDATE mysql.bind_info SET status=%s,update_time=%s WHERE original_sql=%s and default_db=%s`, + expression.Quote(deleted), + expression.Quote(updateTs.String()), + expression.Quote(normdOrigSQL), + expression.Quote(db)) } diff --git a/expression/builtin_string.go b/expression/builtin_string.go index 5d942effe78d3..862385f8eaa3d 100644 --- a/expression/builtin_string.go +++ b/expression/builtin_string.go @@ -2703,6 +2703,11 @@ func (b *builtinQuoteSig) evalString(row chunk.Row) (string, bool, error) { return "NULL", false, err } + return Quote(str), false, nil +} + +// Quote produce a result that can be used as a properly escaped data value in an SQL statement. +func Quote(str string) string { runes := []rune(str) buffer := bytes.NewBufferString("") buffer.WriteRune('\'') @@ -2723,7 +2728,7 @@ func (b *builtinQuoteSig) evalString(row chunk.Row) (string, bool, error) { } buffer.WriteRune('\'') - return buffer.String(), false, nil + return buffer.String() } type binFunctionClass struct {