Skip to content

Commit

Permalink
feat: improve error message for typo in IF NOT EXISTS (#3817)
Browse files Browse the repository at this point in the history
* refactor: improve error message for typo in IF NOT EXISTS

Signed-off-by: tison <[email protected]>

* support table name 'if'

Signed-off-by: tison <[email protected]>

* add sqlness cases

Signed-off-by: tison <[email protected]>

---------

Signed-off-by: tison <[email protected]>
  • Loading branch information
tisonkun authored Apr 28, 2024
1 parent 3dac7cb commit 1bbde15
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 12 deletions.
46 changes: 34 additions & 12 deletions src/sql/src/parsers/create_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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() {
Expand All @@ -86,11 +84,7 @@ impl<'a> ParserContext<'a> {

fn parse_create_database(&mut self) -> Result<Statement> {
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",
Expand All @@ -105,9 +99,8 @@ impl<'a> ParserContext<'a> {

fn parse_create_table(&mut self) -> Result<Statement> {
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()?;

Expand Down Expand Up @@ -144,6 +137,35 @@ impl<'a> ParserContext<'a> {
Ok(Statement::CreateTable(create_table))
}

fn parse_if_not_exist(&mut self) -> Result<bool> {
match self.parser.peek_token().token {
Token::Word(w) if Keyword::IF != w.keyword => return Ok(false),
_ => {}
}

if self.parser.parse_keywords(&[Keyword::IF, 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_keywords(&[Keyword::IF, Keyword::EXISTS]) {
return UnsupportedSnafu {
sql: self.sql,
keyword: "EXISTS",
}
.fail();
}

Ok(false)
}

fn parse_create_table_options(&mut self) -> Result<OptionMap> {
let options = self
.parser
Expand Down
40 changes: 40 additions & 0 deletions tests/cases/standalone/common/create/create_if_not_exists.result
Original file line number Diff line number Diff line change
@@ -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

19 changes: 19 additions & 0 deletions tests/cases/standalone/common/create/create_if_not_exists.sql
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 1bbde15

Please sign in to comment.