Skip to content

Commit

Permalink
feat!: tokenize with locations by default
Browse files Browse the repository at this point in the history
- in parse_sql and try_with_sql
- update test_parser_error_loc
- change test_utils to parse without locations to avoid maintenance overhead

BREAKING CHANGE: changes the default ParserError messages
  • Loading branch information
MartinNowak committed Sep 2, 2023
1 parent a452a80 commit cad04da
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
8 changes: 3 additions & 5 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ impl<'a> Parser<'a> {
debug!("Parsing sql '{}'...", sql);
let tokens = Tokenizer::new(self.dialect, sql)
.with_unescape(self.options.unescape)
.tokenize()?;
Ok(self.with_tokens(tokens))
.tokenize_with_location()?;
Ok(self.with_tokens_with_locations(tokens))
}

/// Parse potentially multiple statements
Expand Down Expand Up @@ -7962,14 +7962,12 @@ mod tests {

#[test]
fn test_parser_error_loc() {
// TODO: Once we thread token locations through the parser, we should update this
// test to assert the locations of the referenced token
let sql = "SELECT this is a syntax error";
let ast = Parser::parse_sql(&GenericDialect, sql);
assert_eq!(
ast,
Err(ParserError::ParserError(
"Expected [NOT] NULL or TRUE|FALSE or [NOT] DISTINCT FROM after IS, found: a"
"Expected [NOT] NULL or TRUE|FALSE or [NOT] DISTINCT FROM after IS, found: a at Line: 1, Column 16"
.to_string()
))
);
Expand Down
8 changes: 7 additions & 1 deletion src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use core::fmt::Debug;

use crate::dialect::*;
use crate::parser::{Parser, ParserError};
use crate::tokenizer::Tokenizer;
use crate::{ast::*, parser::ParserOptions};

/// Tests use the methods on this struct to invoke the parser on one or
Expand Down Expand Up @@ -82,8 +83,13 @@ impl TestedDialects {
/// the result is the same for all tested dialects.
pub fn parse_sql_statements(&self, sql: &str) -> Result<Vec<Statement>, ParserError> {
self.one_of_identical_results(|dialect| {
let mut tokenizer = Tokenizer::new(dialect, sql);
if let Some(options) = &self.options {
tokenizer = tokenizer.with_unescape(options.unescape);
}
let tokens = tokenizer.tokenize()?;
self.new_parser(dialect)
.try_with_sql(sql)?
.with_tokens(tokens)
.parse_statements()
})
// To fail the `ensure_multiple_dialects_are_tested` test:
Expand Down
30 changes: 17 additions & 13 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,12 @@ fn test_eof_after_as() {

#[test]
fn test_no_infix_error() {
let res = Parser::parse_sql(&ClickHouseDialect {}, "ASSERT-URA<<");
let dialects = TestedDialects {
dialects: vec![Box::new(ClickHouseDialect {})],
options: None,
};

let res = dialects.parse_sql_statements("ASSERT-URA<<");
assert_eq!(
ParserError::ParserError("No infix parser for token ShiftLeft".to_string()),
res.unwrap_err()
Expand Down Expand Up @@ -3238,19 +3243,21 @@ fn parse_alter_table_alter_column_type() {
_ => unreachable!(),
}

let res = Parser::parse_sql(
&GenericDialect {},
&format!("{alter_stmt} ALTER COLUMN is_active TYPE TEXT"),
);
let dialect = TestedDialects {
dialects: vec![Box::new(GenericDialect {})],
options: None,
};

let res =
dialect.parse_sql_statements(&format!("{alter_stmt} ALTER COLUMN is_active TYPE TEXT"));
assert_eq!(
ParserError::ParserError("Expected SET/DROP NOT NULL, SET DEFAULT, SET DATA TYPE after ALTER COLUMN, found: TYPE".to_string()),
res.unwrap_err()
);

let res = Parser::parse_sql(
&GenericDialect {},
&format!("{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"),
);
let res = dialect.parse_sql_statements(&format!(
"{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"
));
assert_eq!(
ParserError::ParserError("Expected end of statement, found: USING".to_string()),
res.unwrap_err()
Expand Down Expand Up @@ -3295,10 +3302,7 @@ fn parse_alter_table_drop_constraint() {
_ => unreachable!(),
}

let res = Parser::parse_sql(
&GenericDialect {},
&format!("{alter_stmt} DROP CONSTRAINT is_active TEXT"),
);
let res = parse_sql_statements(&format!("{alter_stmt} DROP CONSTRAINT is_active TEXT"));
assert_eq!(
ParserError::ParserError("Expected end of statement, found: TEXT".to_string()),
res.unwrap_err()
Expand Down

0 comments on commit cad04da

Please sign in to comment.