From e4bef0c4b71f42fe7c115ffc3ee1d7075910a7b1 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Fri, 24 Feb 2017 13:05:07 +0000 Subject: [PATCH] Differentiate between IDENT and EXPR in SQL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously it was possible to CREATE/UPDATE/DELETE path expressions as this would satisfy an IDENT in the SQL parser. Now however, there is a difference between an IDENT and an EXPR… IDENT: person | person_main | person123 EXPR: person | person.path | person[0].path As a result, path expressions are only possible when setting data or setting conditional conditions. --- sql/exprs.go | 2 +- sql/scanner.go | 16 ++++++++++++---- sql/tokens.go | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sql/exprs.go b/sql/exprs.go index a2f19ac6..699ef6a5 100644 --- a/sql/exprs.go +++ b/sql/exprs.go @@ -519,7 +519,7 @@ func (p *parser) parseExpr() (exp Expr, err error) { func (p *parser) parsePart() (exp Expr, err error) { toks := []Token{ - MUL, ID, IDENT, THING, + MUL, ID, EXPR, IDENT, THING, NULL, VOID, EMPTY, MISSING, TRUE, FALSE, STRING, REGION, NUMBER, DOUBLE, NOW, DATE, TIME, DURATION, JSON, ARRAY, PARAM, LPAREN, diff --git a/sql/scanner.go b/sql/scanner.go index 2504f79d..62731128 100644 --- a/sql/scanner.go +++ b/sql/scanner.go @@ -395,11 +395,14 @@ func (s *scanner) scanIdent(chp ...rune) (tok Token, lit string, val interface{} for { if ch := s.next(); ch == eof { break - } else if !isIdentChar(ch) { + } else if isIdentChar(ch) { + buf.WriteRune(ch) + } else if isExprsChar(ch) { + tok = EXPR + buf.WriteRune(ch) + } else { s.undo() break - } else { - buf.WriteRune(ch) } } @@ -839,7 +842,7 @@ func isLetter(ch rune) bool { // isIdentChar returns true if the rune is allowed in a IDENT. func isIdentChar(ch rune) bool { - return isLetter(ch) || isNumber(ch) || ch == '.' || ch == '_' || ch == '*' || ch == '[' || ch == ']' + return isLetter(ch) || isNumber(ch) || ch == '_' } // isThingChar returns true if the rune is allowed in a THING. @@ -847,5 +850,10 @@ func isThingChar(ch rune) bool { return isLetter(ch) || isNumber(ch) || ch == '_' } +// isExprsChar returns true if the rune is allowed in a IDENT. +func isExprsChar(ch rune) bool { + return isLetter(ch) || isNumber(ch) || ch == '.' || ch == '_' || ch == '*' || ch == '[' || ch == ']' +} + // eof represents a marker rune for the end of the reader. var eof = rune(0) diff --git a/sql/tokens.go b/sql/tokens.go index 45e36cc9..a9dc940a 100644 --- a/sql/tokens.go +++ b/sql/tokens.go @@ -32,6 +32,7 @@ const ( DATE // 1970-01-01 TIME // 1970-01-01T00:00:00+00:00 JSON // {"test":true} + EXPR // something[0].value IDENT // something THING // @class:id STRING // "something"