feat: improve error message for typo in IF NOT EXISTS (#3817)

* refactor: improve error message for typo in IF NOT EXISTS

Signed-off-by: tison <wander4096@gmail.com>

* support table name 'if'

Signed-off-by: tison <wander4096@gmail.com>

* add sqlness cases

Signed-off-by: tison <wander4096@gmail.com>

---------

Signed-off-by: tison <wander4096@gmail.com>
This commit is contained in:
tison
2024-04-28 19:20:17 +08:00
committed by GitHub
parent 3dac7cbe37
commit 1bbde15a15
3 changed files with 93 additions and 12 deletions

View File

@@ -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<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",
@@ -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()?;
@@ -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

View File

@@ -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

View File

@@ -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;