diff --git a/src/parser.rs b/src/parser.rs index c468e9be8..352be3b63 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -195,7 +195,7 @@ impl std::error::Error for ParserError {} // By default, allow expressions up to this deep before erroring const DEFAULT_REMAINING_DEPTH: usize = 50; -#[derive(Default)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct ParserOptions { pub trailing_commas: bool, } @@ -6958,6 +6958,7 @@ mod tests { // Character string types: let dialect = TestedDialects { dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})], + options: None, }; test_parse_data_type!(dialect, "CHARACTER", DataType::Character(None)); @@ -7087,6 +7088,7 @@ mod tests { // Character large object types: let dialect = TestedDialects { dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})], + options: None, }; test_parse_data_type!( @@ -7119,6 +7121,7 @@ mod tests { fn test_parse_custom_types() { let dialect = TestedDialects { dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})], + options: None, }; test_parse_data_type!( dialect, @@ -7150,6 +7153,7 @@ mod tests { // Exact numeric types: let dialect = TestedDialects { dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})], + options: None, }; test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None)); @@ -7200,6 +7204,7 @@ mod tests { // Datetime types: let dialect = TestedDialects { dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})], + options: None, }; test_parse_data_type!(dialect, "DATE", DataType::Date); @@ -7311,6 +7316,7 @@ mod tests { let dialect = TestedDialects { dialects: vec![Box::new(GenericDialect {}), Box::new(MySqlDialect {})], + options: None, }; test_parse_table_constraint!( diff --git a/src/test_utils.rs b/src/test_utils.rs index 422ecc77d..d01bbbab9 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -26,17 +26,27 @@ use alloc::{ }; use core::fmt::Debug; -use crate::ast::*; use crate::dialect::*; use crate::parser::{Parser, ParserError}; +use crate::{ast::*, parser::ParserOptions}; /// Tests use the methods on this struct to invoke the parser on one or /// multiple dialects. pub struct TestedDialects { pub dialects: Vec>, + pub options: Option, } impl TestedDialects { + fn new_parser<'a>(&self, dialect: &'a dyn Dialect) -> Parser<'a> { + let parser = Parser::new(dialect); + if let Some(options) = &self.options { + parser.with_options(options.clone()) + } else { + parser + } + } + /// Run the given function for all of `self.dialects`, assert that they /// return the same result, and return that result. pub fn one_of_identical_results(&self, f: F) -> T @@ -63,7 +73,7 @@ impl TestedDialects { F: Fn(&mut Parser) -> T, { self.one_of_identical_results(|dialect| { - let mut parser = Parser::new(dialect).try_with_sql(sql).unwrap(); + let mut parser = self.new_parser(dialect).try_with_sql(sql).unwrap(); f(&mut parser) }) } @@ -71,7 +81,11 @@ impl TestedDialects { /// Parses a single SQL string into multiple statements, ensuring /// the result is the same for all tested dialects. pub fn parse_sql_statements(&self, sql: &str) -> Result, ParserError> { - self.one_of_identical_results(|dialect| Parser::parse_sql(dialect, sql)) + self.one_of_identical_results(|dialect| { + self.new_parser(dialect) + .try_with_sql(sql)? + .parse_statements() + }) // To fail the `ensure_multiple_dialects_are_tested` test: // Parser::parse_sql(&**self.dialects.first().unwrap(), sql) } @@ -155,6 +169,7 @@ pub fn all_dialects() -> TestedDialects { Box::new(BigQueryDialect {}), Box::new(SQLiteDialect {}), ], + options: None, } } diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index 11a8c6e5c..0850bd4bf 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -406,12 +406,14 @@ fn test_select_wildcard_with_replace() { fn bigquery() -> TestedDialects { TestedDialects { dialects: vec![Box::new(BigQueryDialect {})], + options: None, } } fn bigquery_and_generic() -> TestedDialects { TestedDialects { dialects: vec![Box::new(BigQueryDialect {}), Box::new(GenericDialect {})], + options: None, } } diff --git a/tests/sqlparser_clickhouse.rs b/tests/sqlparser_clickhouse.rs index 8af8dd839..bb0ec48fa 100644 --- a/tests/sqlparser_clickhouse.rs +++ b/tests/sqlparser_clickhouse.rs @@ -329,5 +329,6 @@ fn parse_create_table() { fn clickhouse() -> TestedDialects { TestedDialects { dialects: vec![Box::new(ClickHouseDialect {})], + options: None, } } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 27a642dbe..16fd623dd 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -28,7 +28,7 @@ use sqlparser::dialect::{ MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect, SQLiteDialect, SnowflakeDialect, }; use sqlparser::keywords::ALL_KEYWORDS; -use sqlparser::parser::{Parser, ParserError}; +use sqlparser::parser::{Parser, ParserError, ParserOptions}; use test_utils::{ all_dialects, assert_eq_vec, expr_from_projection, join, number, only, table, table_alias, TestedDialects, @@ -201,6 +201,7 @@ fn parse_update_set_from() { Box::new(RedshiftSqlDialect {}), Box::new(MsSqlDialect {}), ], + options: None, }; let stmt = dialects.verified_stmt(sql); assert_eq!( @@ -949,6 +950,7 @@ fn parse_exponent_in_select() -> Result<(), ParserError> { Box::new(SnowflakeDialect {}), Box::new(SQLiteDialect {}), ], + options: None, }; let sql = "SELECT 10e-20, 1e3, 1e+3, 1e3a, 1e, 0.5e2"; let mut select = dialects.parse_sql_statements(sql)?; @@ -1386,6 +1388,7 @@ pub fn all_dialects_but_pg() -> TestedDialects { .into_iter() .filter(|x| !x.is::()) .collect(), + options: None, } } @@ -2055,6 +2058,7 @@ fn parse_array_agg_func() { Box::new(AnsiDialect {}), Box::new(HiveDialect {}), ], + options: None, }; for sql in [ @@ -2254,6 +2258,7 @@ fn parse_create_table_hive_array() { // Parsing [] type arrays does not work in MsSql since [ is used in is_delimited_identifier_start let dialects = TestedDialects { dialects: vec![Box::new(PostgreSqlDialect {}), Box::new(HiveDialect {})], + options: None, }; let sql = "CREATE TABLE IF NOT EXISTS something (name int, val array)"; match dialects.one_statement_parses_to( @@ -2296,6 +2301,7 @@ fn parse_create_table_hive_array() { Box::new(HiveDialect {}), Box::new(MySqlDialect {}), ], + options: None, }; let sql = "CREATE TABLE IF NOT EXISTS something (name int, val array TestedDialects { TestedDialects { dialects: vec![Box::new(HiveDialect {})], + options: None, } } diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs index 41b0803e4..1f708b5e7 100644 --- a/tests/sqlparser_mssql.rs +++ b/tests/sqlparser_mssql.rs @@ -305,10 +305,12 @@ fn parse_similar_to() { fn ms() -> TestedDialects { TestedDialects { dialects: vec![Box::new(MsSqlDialect {})], + options: None, } } fn ms_and_generic() -> TestedDialects { TestedDialects { dialects: vec![Box::new(MsSqlDialect {}), Box::new(GenericDialect {})], + options: None, } } diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 1bdce0009..1c479bb18 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -1350,12 +1350,14 @@ fn parse_create_table_with_fulltext_definition_should_not_accept_constraint_name fn mysql() -> TestedDialects { TestedDialects { dialects: vec![Box::new(MySqlDialect {})], + options: None, } } fn mysql_and_generic() -> TestedDialects { TestedDialects { dialects: vec![Box::new(MySqlDialect {}), Box::new(GenericDialect {})], + options: None, } } diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index af9783f35..09db64293 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -2052,12 +2052,14 @@ fn parse_on_commit() { fn pg() -> TestedDialects { TestedDialects { dialects: vec![Box::new(PostgreSqlDialect {})], + options: None, } } fn pg_and_generic() -> TestedDialects { TestedDialects { dialects: vec![Box::new(PostgreSqlDialect {}), Box::new(GenericDialect {})], + options: None, } } diff --git a/tests/sqlparser_redshift.rs b/tests/sqlparser_redshift.rs index 7597ee981..d3a676939 100644 --- a/tests/sqlparser_redshift.rs +++ b/tests/sqlparser_redshift.rs @@ -260,6 +260,7 @@ fn parse_similar_to() { fn redshift() -> TestedDialects { TestedDialects { dialects: vec![Box::new(RedshiftSqlDialect {})], + options: None, } } diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 8bcbb7b5a..d1a63dc86 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -396,12 +396,14 @@ fn test_array_agg_func() { fn snowflake() -> TestedDialects { TestedDialects { dialects: vec![Box::new(SnowflakeDialect {})], + options: None, } } fn snowflake_and_generic() -> TestedDialects { TestedDialects { dialects: vec![Box::new(SnowflakeDialect {}), Box::new(GenericDialect {})], + options: None, } } diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 8fc3a8d63..31d2dd97f 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -245,6 +245,7 @@ fn parse_similar_to() { fn sqlite() -> TestedDialects { TestedDialects { dialects: vec![Box::new(SQLiteDialect {})], + options: None, } } @@ -252,5 +253,6 @@ fn sqlite_and_generic() -> TestedDialects { TestedDialects { // we don't have a separate SQLite dialect, so test only the generic dialect for now dialects: vec![Box::new(SQLiteDialect {}), Box::new(GenericDialect {})], + options: None, } }