From 6967183b67f239e1b771d3caa9613a72f85c4345 Mon Sep 17 00:00:00 2001 From: Andre Marianiello Date: Thu, 30 May 2019 11:23:48 -0400 Subject: [PATCH 1/2] Fix parsing of quoted identifiers in SHOW CREATE TABLE queries Signed-off-by: Andre Marianiello --- sql/parse/parse_test.go | 11 ++++++--- sql/parse/util.go | 52 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/sql/parse/parse_test.go b/sql/parse/parse_test.go index f2caa2ba0..e23b33c31 100644 --- a/sql/parse/parse_test.go +++ b/sql/parse/parse_test.go @@ -1007,9 +1007,14 @@ var fixtures = map[string]sql.Node{ ), plan.NewShowCollation(), ), - `ROLLBACK`: plan.NewRollback(), - "SHOW CREATE TABLE `mytable`": plan.NewShowCreateTable("", nil, "mytable"), - "SHOW CREATE TABLE `mydb`.`mytable`": plan.NewShowCreateTable("mydb", nil, "mytable"), + `ROLLBACK`: plan.NewRollback(), + "SHOW CREATE TABLE `mytable`": plan.NewShowCreateTable("", nil, "mytable"), + "SHOW CREATE TABLE `mydb`.`mytable`": plan.NewShowCreateTable("mydb", nil, "mytable"), + "SHOW CREATE TABLE `my.table`": plan.NewShowCreateTable("", nil, "my.table"), + "SHOW CREATE TABLE `my.db`.`my.table`": plan.NewShowCreateTable("my.db", nil, "my.table"), + "SHOW CREATE TABLE `my``table`": plan.NewShowCreateTable("", nil, "my`table"), + "SHOW CREATE TABLE `my``db`.`my``table`": plan.NewShowCreateTable("my`db", nil, "my`table"), + "SHOW CREATE TABLE ````": plan.NewShowCreateTable("", nil, "`"), `SELECT '2018-05-01' + INTERVAL 1 DAY`: plan.NewProject( []sql.Expression{expression.NewArithmetic( expression.NewLiteral("2018-05-01", sql.Text), diff --git a/sql/parse/util.go b/sql/parse/util.go index e76de3771..f2826edf4 100644 --- a/sql/parse/util.go +++ b/sql/parse/util.go @@ -144,6 +144,36 @@ func readValidIdentRune(r *bufio.Reader, buf *bytes.Buffer) error { return nil } +func readValidQuotedIdentRune(r *bufio.Reader, buf *bytes.Buffer) error { + bs, err := r.Peek(2) + if err != nil { + return err + } + + if bs[0] == '`' && bs[1] == '`' { + if _, _, err := r.ReadRune(); err != nil { + return err + } + if _, _, err := r.ReadRune(); err != nil { + return err + } + buf.WriteRune('`') + return nil + } + + if bs[0] == '`' && bs[1] != '`' { + return io.EOF + } + + if _, _, err := r.ReadRune(); err != nil { + return err + } + + buf.WriteByte(bs[0]) + + return nil +} + func unreadString(r *bufio.Reader, str string) { nr := *r r.Reset(io.MultiReader(strings.NewReader(str), &nr)) @@ -169,6 +199,26 @@ func readIdent(ident *string) parseFunc { } } +func readQuotedIdent(ident *string) parseFunc { + return func(r *bufio.Reader) error { + var buf bytes.Buffer + if err := readLetter(r, &buf); err != nil { + return err + } + + for { + if err := readValidQuotedIdentRune(r, &buf); err == io.EOF { + break + } else if err != nil { + return err + } + } + + *ident = strings.ToLower(buf.String()) + return nil + } +} + func oneOf(options ...string) parseFunc { return func(r *bufio.Reader) error { var ident string @@ -235,7 +285,7 @@ func readQuotableIdent(ident *string) parseFunc { if nextChar[0] == '`' { steps = parseFuncs{ expectQuote, - readIdent(ident), + readQuotedIdent(ident), expectQuote, } } else { From 0fd62c4389d79c84b05c39986e515b21c007d8e9 Mon Sep 17 00:00:00 2001 From: Andre Marianiello Date: Thu, 30 May 2019 12:09:09 -0400 Subject: [PATCH 2/2] Make sure quoted identifiers start with any character Signed-off-by: Andre Marianiello --- sql/parse/parse_test.go | 1 + sql/parse/util.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/parse/parse_test.go b/sql/parse/parse_test.go index e23b33c31..02b69d283 100644 --- a/sql/parse/parse_test.go +++ b/sql/parse/parse_test.go @@ -1015,6 +1015,7 @@ var fixtures = map[string]sql.Node{ "SHOW CREATE TABLE `my``table`": plan.NewShowCreateTable("", nil, "my`table"), "SHOW CREATE TABLE `my``db`.`my``table`": plan.NewShowCreateTable("my`db", nil, "my`table"), "SHOW CREATE TABLE ````": plan.NewShowCreateTable("", nil, "`"), + "SHOW CREATE TABLE `.`": plan.NewShowCreateTable("", nil, "."), `SELECT '2018-05-01' + INTERVAL 1 DAY`: plan.NewProject( []sql.Expression{expression.NewArithmetic( expression.NewLiteral("2018-05-01", sql.Text), diff --git a/sql/parse/util.go b/sql/parse/util.go index f2826edf4..12df75710 100644 --- a/sql/parse/util.go +++ b/sql/parse/util.go @@ -202,7 +202,7 @@ func readIdent(ident *string) parseFunc { func readQuotedIdent(ident *string) parseFunc { return func(r *bufio.Reader) error { var buf bytes.Buffer - if err := readLetter(r, &buf); err != nil { + if err := readValidQuotedIdentRune(r, &buf); err != nil { return err }