Skip to content

Commit c4aa802

Browse files
committed
test: add tests for trailing commas
1 parent 3b1076c commit c4aa802

12 files changed

+81
-5
lines changed

src/parser.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl std::error::Error for ParserError {}
195195
// By default, allow expressions up to this deep before erroring
196196
const DEFAULT_REMAINING_DEPTH: usize = 50;
197197

198-
#[derive(Default)]
198+
#[derive(Default, Clone)]
199199
pub struct ParserOptions {
200200
pub trailing_commas: bool,
201201
}
@@ -6958,6 +6958,7 @@ mod tests {
69586958
// Character string types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-string-type>
69596959
let dialect = TestedDialects {
69606960
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
6961+
options: None,
69616962
};
69626963

69636964
test_parse_data_type!(dialect, "CHARACTER", DataType::Character(None));
@@ -7087,6 +7088,7 @@ mod tests {
70877088
// Character large object types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-length>
70887089
let dialect = TestedDialects {
70897090
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
7091+
options: None,
70907092
};
70917093

70927094
test_parse_data_type!(
@@ -7119,6 +7121,7 @@ mod tests {
71197121
fn test_parse_custom_types() {
71207122
let dialect = TestedDialects {
71217123
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
7124+
options: None,
71227125
};
71237126
test_parse_data_type!(
71247127
dialect,
@@ -7150,6 +7153,7 @@ mod tests {
71507153
// Exact numeric types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type>
71517154
let dialect = TestedDialects {
71527155
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
7156+
options: None,
71537157
};
71547158

71557159
test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None));
@@ -7200,6 +7204,7 @@ mod tests {
72007204
// Datetime types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type>
72017205
let dialect = TestedDialects {
72027206
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
7207+
options: None,
72037208
};
72047209

72057210
test_parse_data_type!(dialect, "DATE", DataType::Date);
@@ -7311,6 +7316,7 @@ mod tests {
73117316

73127317
let dialect = TestedDialects {
73137318
dialects: vec![Box::new(GenericDialect {}), Box::new(MySqlDialect {})],
7319+
options: None,
73147320
};
73157321

73167322
test_parse_table_constraint!(

src/test_utils.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,27 @@ use alloc::{
2626
};
2727
use core::fmt::Debug;
2828

29-
use crate::ast::*;
3029
use crate::dialect::*;
3130
use crate::parser::{Parser, ParserError};
31+
use crate::{ast::*, parser::ParserOptions};
3232

3333
/// Tests use the methods on this struct to invoke the parser on one or
3434
/// multiple dialects.
3535
pub struct TestedDialects {
3636
pub dialects: Vec<Box<dyn Dialect>>,
37+
pub options: Option<ParserOptions>,
3738
}
3839

3940
impl TestedDialects {
41+
fn new_parser<'a>(&self, dialect: &'a dyn Dialect) -> Parser<'a> {
42+
let parser = Parser::new(dialect);
43+
if let Some(options) = &self.options {
44+
parser.with_options(options.clone())
45+
} else {
46+
parser
47+
}
48+
}
49+
4050
/// Run the given function for all of `self.dialects`, assert that they
4151
/// return the same result, and return that result.
4252
pub fn one_of_identical_results<F, T: Debug + PartialEq>(&self, f: F) -> T
@@ -63,15 +73,19 @@ impl TestedDialects {
6373
F: Fn(&mut Parser) -> T,
6474
{
6575
self.one_of_identical_results(|dialect| {
66-
let mut parser = Parser::new(dialect).try_with_sql(sql).unwrap();
76+
let mut parser = self.new_parser(dialect).try_with_sql(sql).unwrap();
6777
f(&mut parser)
6878
})
6979
}
7080

7181
/// Parses a single SQL string into multiple statements, ensuring
7282
/// the result is the same for all tested dialects.
7383
pub fn parse_sql_statements(&self, sql: &str) -> Result<Vec<Statement>, ParserError> {
74-
self.one_of_identical_results(|dialect| Parser::parse_sql(dialect, sql))
84+
self.one_of_identical_results(|dialect| {
85+
self.new_parser(dialect)
86+
.try_with_sql(sql)?
87+
.parse_statements()
88+
})
7589
// To fail the `ensure_multiple_dialects_are_tested` test:
7690
// Parser::parse_sql(&**self.dialects.first().unwrap(), sql)
7791
}
@@ -155,6 +169,7 @@ pub fn all_dialects() -> TestedDialects {
155169
Box::new(BigQueryDialect {}),
156170
Box::new(SQLiteDialect {}),
157171
],
172+
options: None,
158173
}
159174
}
160175

tests/sqlparser_bigquery.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,14 @@ fn test_select_wildcard_with_replace() {
406406
fn bigquery() -> TestedDialects {
407407
TestedDialects {
408408
dialects: vec![Box::new(BigQueryDialect {})],
409+
options: None,
409410
}
410411
}
411412

412413
fn bigquery_and_generic() -> TestedDialects {
413414
TestedDialects {
414415
dialects: vec![Box::new(BigQueryDialect {}), Box::new(GenericDialect {})],
416+
options: None,
415417
}
416418
}
417419

tests/sqlparser_clickhouse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,5 +329,6 @@ fn parse_create_table() {
329329
fn clickhouse() -> TestedDialects {
330330
TestedDialects {
331331
dialects: vec![Box::new(ClickHouseDialect {})],
332+
options: None,
332333
}
333334
}

tests/sqlparser_common.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use sqlparser::dialect::{
2828
MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect, SQLiteDialect, SnowflakeDialect,
2929
};
3030
use sqlparser::keywords::ALL_KEYWORDS;
31-
use sqlparser::parser::{Parser, ParserError};
31+
use sqlparser::parser::{Parser, ParserError, ParserOptions};
3232
use test_utils::{
3333
all_dialects, assert_eq_vec, expr_from_projection, join, number, only, table, table_alias,
3434
TestedDialects,
@@ -201,6 +201,7 @@ fn parse_update_set_from() {
201201
Box::new(RedshiftSqlDialect {}),
202202
Box::new(MsSqlDialect {}),
203203
],
204+
options: None,
204205
};
205206
let stmt = dialects.verified_stmt(sql);
206207
assert_eq!(
@@ -949,6 +950,7 @@ fn parse_exponent_in_select() -> Result<(), ParserError> {
949950
Box::new(SnowflakeDialect {}),
950951
Box::new(SQLiteDialect {}),
951952
],
953+
options: None,
952954
};
953955
let sql = "SELECT 10e-20, 1e3, 1e+3, 1e3a, 1e, 0.5e2";
954956
let mut select = dialects.parse_sql_statements(sql)?;
@@ -1386,6 +1388,7 @@ pub fn all_dialects_but_pg() -> TestedDialects {
13861388
.into_iter()
13871389
.filter(|x| !x.is::<PostgreSqlDialect>())
13881390
.collect(),
1391+
options: None,
13891392
}
13901393
}
13911394

@@ -2055,6 +2058,7 @@ fn parse_array_agg_func() {
20552058
Box::new(AnsiDialect {}),
20562059
Box::new(HiveDialect {}),
20572060
],
2061+
options: None,
20582062
};
20592063

20602064
for sql in [
@@ -2254,6 +2258,7 @@ fn parse_create_table_hive_array() {
22542258
// Parsing [] type arrays does not work in MsSql since [ is used in is_delimited_identifier_start
22552259
let dialects = TestedDialects {
22562260
dialects: vec![Box::new(PostgreSqlDialect {}), Box::new(HiveDialect {})],
2261+
options: None,
22572262
};
22582263
let sql = "CREATE TABLE IF NOT EXISTS something (name int, val array<int>)";
22592264
match dialects.one_statement_parses_to(
@@ -2296,6 +2301,7 @@ fn parse_create_table_hive_array() {
22962301
Box::new(HiveDialect {}),
22972302
Box::new(MySqlDialect {}),
22982303
],
2304+
options: None,
22992305
};
23002306
let sql = "CREATE TABLE IF NOT EXISTS something (name int, val array<int)";
23012307

@@ -2841,6 +2847,7 @@ fn parse_alter_table_add_column_if_not_exists() {
28412847
Box::new(BigQueryDialect {}),
28422848
Box::new(GenericDialect {}),
28432849
],
2850+
options: None,
28442851
};
28452852

28462853
match dialects.verified_stmt("ALTER TABLE tab ADD IF NOT EXISTS foo TEXT") {
@@ -3898,6 +3905,7 @@ fn parse_unnest() {
38983905
}
38993906
let dialects = TestedDialects {
39003907
dialects: vec![Box::new(BigQueryDialect {}), Box::new(GenericDialect {})],
3908+
options: None,
39013909
};
39023910
// 1. both Alias and WITH OFFSET clauses.
39033911
chk(
@@ -6137,6 +6145,7 @@ fn test_placeholder() {
61376145
// Note: `$` is the starting word for the HiveDialect identifier
61386146
// Box::new(sqlparser::dialect::HiveDialect {}),
61396147
],
6148+
options: None,
61406149
};
61416150
let sql = "SELECT * FROM student WHERE id = $Id1";
61426151
let ast = dialects.verified_only_select(sql);
@@ -6867,6 +6876,7 @@ fn parse_non_latin_identifiers() {
68676876
Box::new(RedshiftSqlDialect {}),
68686877
Box::new(MySqlDialect {}),
68696878
],
6879+
options: None,
68706880
};
68716881

68726882
supported_dialects.verified_stmt("SELECT a.説明 FROM test.public.inter01 AS a");
@@ -6876,3 +6886,32 @@ fn parse_non_latin_identifiers() {
68766886
.parse_sql_statements("SELECT 💝 FROM table1")
68776887
.is_err());
68786888
}
6889+
6890+
#[test]
6891+
fn parse_trailing_comma() {
6892+
let trailing_commas = TestedDialects {
6893+
dialects: vec![Box::new(GenericDialect {})],
6894+
options: Some(ParserOptions {
6895+
trailing_commas: true,
6896+
}),
6897+
};
6898+
6899+
// We shouldn't verify, because trailing commas will not get generated back
6900+
trailing_commas
6901+
.parse_sql_statements("SELECT album_id, name, FROM track")
6902+
.unwrap();
6903+
6904+
trailing_commas
6905+
.parse_sql_statements("SELECT * FROM track ORDER BY milliseconds,")
6906+
.unwrap();
6907+
6908+
trailing_commas
6909+
.parse_sql_statements("SELECT DISTINCT ON (album_id,) name FROM track")
6910+
.unwrap();
6911+
6912+
trailing_commas.verified_stmt("SELECT album_id, name FROM track");
6913+
6914+
trailing_commas.verified_stmt("SELECT * FROM track ORDER BY milliseconds");
6915+
6916+
trailing_commas.verified_stmt("SELECT DISTINCT ON (album_id) name FROM track");
6917+
}

tests/sqlparser_hive.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ fn parse_create_function() {
267267

268268
let generic = TestedDialects {
269269
dialects: vec![Box::new(GenericDialect {})],
270+
options: None,
270271
};
271272

272273
assert_eq!(
@@ -473,5 +474,6 @@ fn parse_similar_to() {
473474
fn hive() -> TestedDialects {
474475
TestedDialects {
475476
dialects: vec![Box::new(HiveDialect {})],
477+
options: None,
476478
}
477479
}

tests/sqlparser_mssql.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,12 @@ fn parse_similar_to() {
305305
fn ms() -> TestedDialects {
306306
TestedDialects {
307307
dialects: vec![Box::new(MsSqlDialect {})],
308+
options: None,
308309
}
309310
}
310311
fn ms_and_generic() -> TestedDialects {
311312
TestedDialects {
312313
dialects: vec![Box::new(MsSqlDialect {}), Box::new(GenericDialect {})],
314+
options: None,
313315
}
314316
}

tests/sqlparser_mysql.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,12 +1350,14 @@ fn parse_create_table_with_fulltext_definition_should_not_accept_constraint_name
13501350
fn mysql() -> TestedDialects {
13511351
TestedDialects {
13521352
dialects: vec![Box::new(MySqlDialect {})],
1353+
options: None,
13531354
}
13541355
}
13551356

13561357
fn mysql_and_generic() -> TestedDialects {
13571358
TestedDialects {
13581359
dialects: vec![Box::new(MySqlDialect {}), Box::new(GenericDialect {})],
1360+
options: None,
13591361
}
13601362
}
13611363

tests/sqlparser_postgres.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,12 +2052,14 @@ fn parse_on_commit() {
20522052
fn pg() -> TestedDialects {
20532053
TestedDialects {
20542054
dialects: vec![Box::new(PostgreSqlDialect {})],
2055+
options: None,
20552056
}
20562057
}
20572058

20582059
fn pg_and_generic() -> TestedDialects {
20592060
TestedDialects {
20602061
dialects: vec![Box::new(PostgreSqlDialect {}), Box::new(GenericDialect {})],
2062+
options: None,
20612063
}
20622064
}
20632065

tests/sqlparser_redshift.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ fn parse_similar_to() {
260260
fn redshift() -> TestedDialects {
261261
TestedDialects {
262262
dialects: vec![Box::new(RedshiftSqlDialect {})],
263+
options: None,
263264
}
264265
}
265266

tests/sqlparser_snowflake.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,14 @@ fn test_array_agg_func() {
396396
fn snowflake() -> TestedDialects {
397397
TestedDialects {
398398
dialects: vec![Box::new(SnowflakeDialect {})],
399+
options: None,
399400
}
400401
}
401402

402403
fn snowflake_and_generic() -> TestedDialects {
403404
TestedDialects {
404405
dialects: vec![Box::new(SnowflakeDialect {}), Box::new(GenericDialect {})],
406+
options: None,
405407
}
406408
}
407409

tests/sqlparser_sqlite.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,14 @@ fn parse_similar_to() {
245245
fn sqlite() -> TestedDialects {
246246
TestedDialects {
247247
dialects: vec![Box::new(SQLiteDialect {})],
248+
options: None,
248249
}
249250
}
250251

251252
fn sqlite_and_generic() -> TestedDialects {
252253
TestedDialects {
253254
// we don't have a separate SQLite dialect, so test only the generic dialect for now
254255
dialects: vec![Box::new(SQLiteDialect {}), Box::new(GenericDialect {})],
256+
options: None,
255257
}
256258
}

0 commit comments

Comments
 (0)