From 21e3eb3611596141c9d3b126ff92865486004380 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 27 Apr 2024 00:42:51 +0800 Subject: [PATCH 1/3] refactor: improve error message for typo in IF NOT EXISTS Signed-off-by: tison --- src/sql/src/parsers/create_parser.rs | 45 ++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/sql/src/parsers/create_parser.rs b/src/sql/src/parsers/create_parser.rs index 20d2ef8eab30..71cd968f46a5 100644 --- a/src/sql/src/parsers/create_parser.rs +++ b/src/sql/src/parsers/create_parser.rs @@ -28,7 +28,7 @@ use table::requests::validate_table_option; use crate::ast::{ColumnDef, Ident, TableConstraint}; use crate::error::{ self, InvalidColumnOptionSnafu, InvalidTableOptionSnafu, InvalidTimeIndexSnafu, - MissingTimeIndexSnafu, Result, SyntaxSnafu, + MissingTimeIndexSnafu, Result, SyntaxSnafu, UnexpectedSnafu, UnsupportedSnafu, }; use crate::parser::ParserContext; use crate::statements::create::{ @@ -63,9 +63,7 @@ impl<'a> ParserContext<'a> { self.parser .expect_keyword(Keyword::TABLE) .context(SyntaxSnafu)?; - let if_not_exists = - self.parser - .parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); + let if_not_exists = self.parse_if_not_exist()?; let table_name = self.intern_parse_table_name()?; let (columns, constraints) = self.parse_columns()?; if !columns.is_empty() { @@ -86,11 +84,7 @@ impl<'a> ParserContext<'a> { fn parse_create_database(&mut self) -> Result { let _ = self.parser.next_token(); - - let if_not_exists = - self.parser - .parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); - + let if_not_exists = self.parse_if_not_exist()?; let database_name = self.parse_object_name().context(error::UnexpectedSnafu { sql: self.sql, expected: "a database name", @@ -105,9 +99,8 @@ impl<'a> ParserContext<'a> { fn parse_create_table(&mut self) -> Result { let _ = self.parser.next_token(); - let if_not_exists = - self.parser - .parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); + + let if_not_exists = self.parse_if_not_exist()?; let table_name = self.intern_parse_table_name()?; @@ -144,6 +137,34 @@ impl<'a> ParserContext<'a> { Ok(Statement::CreateTable(create_table)) } + fn parse_if_not_exist(&mut self) -> Result { + if !self.parser.parse_keyword(Keyword::IF) { + return Ok(false); + } + + if self.parser.parse_keyword(Keyword::NOT) { + return self + .parser + .expect_keyword(Keyword::EXISTS) + .map(|_| true) + .context(UnexpectedSnafu { + sql: self.sql, + expected: "EXISTS", + actual: self.peek_token_as_string(), + }); + } + + if self.parser.parse_keyword(Keyword::EXISTS) { + return UnsupportedSnafu { + sql: self.sql, + keyword: "EXISTS", + } + .fail(); + } + + Ok(false) + } + fn parse_create_table_options(&mut self) -> Result { let options = self .parser From b8aa23a14791dd9a149a5b5d520b585d615ae315 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 27 Apr 2024 01:08:18 +0800 Subject: [PATCH 2/3] support table name 'if' Signed-off-by: tison --- src/sql/src/parsers/create_parser.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sql/src/parsers/create_parser.rs b/src/sql/src/parsers/create_parser.rs index 71cd968f46a5..f6a967581fde 100644 --- a/src/sql/src/parsers/create_parser.rs +++ b/src/sql/src/parsers/create_parser.rs @@ -138,11 +138,12 @@ impl<'a> ParserContext<'a> { } fn parse_if_not_exist(&mut self) -> Result { - if !self.parser.parse_keyword(Keyword::IF) { - return Ok(false); + match self.parser.peek_token().token { + Token::Word(w) if Keyword::IF != w.keyword => return Ok(false), + _ => {} } - if self.parser.parse_keyword(Keyword::NOT) { + if self.parser.parse_keywords(&[Keyword::IF, Keyword::NOT]) { return self .parser .expect_keyword(Keyword::EXISTS) @@ -154,7 +155,7 @@ impl<'a> ParserContext<'a> { }); } - if self.parser.parse_keyword(Keyword::EXISTS) { + if self.parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]) { return UnsupportedSnafu { sql: self.sql, keyword: "EXISTS", From 0c4282dc91434759628c78dfb24a7c49f9ac86a0 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 27 Apr 2024 23:11:39 +0800 Subject: [PATCH 3/3] add sqlness cases Signed-off-by: tison --- .../common/create/create_if_not_exists.result | 40 +++++++++++++++++++ .../common/create/create_if_not_exists.sql | 19 +++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/cases/standalone/common/create/create_if_not_exists.result create mode 100644 tests/cases/standalone/common/create/create_if_not_exists.sql diff --git a/tests/cases/standalone/common/create/create_if_not_exists.result b/tests/cases/standalone/common/create/create_if_not_exists.result new file mode 100644 index 000000000000..e07b7b45dcb4 --- /dev/null +++ b/tests/cases/standalone/common/create/create_if_not_exists.result @@ -0,0 +1,40 @@ +CREATE TABLE IF NOT EXIST t(); + +Error: 2000(InvalidSyntax), Unexpected token while parsing SQL statement: CREATE TABLE IF NOT EXIST t();, expected: 'EXISTS', found: EXIST: sql parser error: Expected EXISTS, found: EXIST at Line: 1, Column 21 + +CREATE TABLE IF NOT t(); + +Error: 2000(InvalidSyntax), Unexpected token while parsing SQL statement: CREATE TABLE IF NOT t();, expected: 'EXISTS', found: t: sql parser error: Expected EXISTS, found: t at Line: 1, Column 21 + +CREATE TABLE IF EXISTS t(); + +Error: 1001(Unsupported), SQL statement is not supported: CREATE TABLE IF EXISTS t();, keyword: EXISTS + +CREATE TABLE IF NOT EXISTS t(); + +Error: 2000(InvalidSyntax), Missing time index constraint + +CREATE TABLE t(); + +Error: 2000(InvalidSyntax), Missing time index constraint + +CREATE TABLE t(ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +CREATE TABLE IF(); + +Error: 2000(InvalidSyntax), Missing time index constraint + +CREATE TABLE IF(ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +DROP TABLE t; + +Affected Rows: 0 + +DROP TABLE IF; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/create/create_if_not_exists.sql b/tests/cases/standalone/common/create/create_if_not_exists.sql new file mode 100644 index 000000000000..9d6366c73542 --- /dev/null +++ b/tests/cases/standalone/common/create/create_if_not_exists.sql @@ -0,0 +1,19 @@ +CREATE TABLE IF NOT EXIST t(); + +CREATE TABLE IF NOT t(); + +CREATE TABLE IF EXISTS t(); + +CREATE TABLE IF NOT EXISTS t(); + +CREATE TABLE t(); + +CREATE TABLE t(ts TIMESTAMP TIME INDEX); + +CREATE TABLE IF(); + +CREATE TABLE IF(ts TIMESTAMP TIME INDEX); + +DROP TABLE t; + +DROP TABLE IF;