1#[cfg(not(feature = "std"))]
26use alloc::{
27 boxed::Box,
28 string::{String, ToString},
29 vec,
30 vec::Vec,
31};
32use core::fmt::Debug;
33
34use crate::dialect::*;
35use crate::parser::{Parser, ParserError};
36use crate::tokenizer::{Token, Tokenizer};
37use crate::{ast::*, parser::ParserOptions};
38
39#[cfg(test)]
40use pretty_assertions::assert_eq;
41
42pub struct TestedDialects {
45 pub dialects: Vec<Box<dyn Dialect>>,
46 pub options: Option<ParserOptions>,
47 pub recursion_limit: Option<usize>,
48}
49
50impl TestedDialects {
51 pub fn new(dialects: Vec<Box<dyn Dialect>>) -> Self {
53 Self {
54 dialects,
55 options: None,
56 recursion_limit: None,
57 }
58 }
59
60 pub fn new_with_options(dialects: Vec<Box<dyn Dialect>>, options: ParserOptions) -> Self {
61 Self {
62 dialects,
63 options: Some(options),
64 recursion_limit: None,
65 }
66 }
67
68 pub fn with_recursion_limit(mut self, recursion_limit: usize) -> Self {
69 self.recursion_limit = Some(recursion_limit);
70 self
71 }
72
73 fn new_parser<'a>(&self, dialect: &'a dyn Dialect) -> Parser<'a> {
74 let parser = Parser::new(dialect);
75 let parser = if let Some(options) = &self.options {
76 parser.with_options(options.clone())
77 } else {
78 parser
79 };
80
81 let parser = if let Some(recursion_limit) = &self.recursion_limit {
82 parser.with_recursion_limit(*recursion_limit)
83 } else {
84 parser
85 };
86
87 parser
88 }
89
90 pub fn one_of_identical_results<F, T: Debug + PartialEq>(&self, f: F) -> T
93 where
94 F: Fn(&dyn Dialect) -> T,
95 {
96 let parse_results = self.dialects.iter().map(|dialect| (dialect, f(&**dialect)));
97 parse_results
98 .fold(None, |s, (dialect, parsed)| {
99 if let Some((prev_dialect, prev_parsed)) = s {
100 match (&prev_parsed, &parsed) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::Some(format_args!("Parse results with {0:?} are different from {1:?}",
prev_dialect, dialect)));
}
}
};assert_eq!(
101 prev_parsed, parsed,
102 "Parse results with {prev_dialect:?} are different from {dialect:?}"
103 );
104 }
105 Some((dialect, parsed))
106 })
107 .expect("tested dialects cannot be empty")
108 .1
109 }
110
111 pub fn run_parser_method<F, T: Debug + PartialEq>(&self, sql: &str, f: F) -> T
112 where
113 F: Fn(&mut Parser) -> T,
114 {
115 self.one_of_identical_results(|dialect| {
116 let mut parser = self.new_parser(dialect).try_with_sql(sql).unwrap();
117 f(&mut parser)
118 })
119 }
120
121 pub fn parse_sql_statements(&self, sql: &str) -> Result<Vec<Statement>, ParserError> {
124 self.one_of_identical_results(|dialect| {
125 let mut tokenizer = Tokenizer::new(dialect, sql);
126 if let Some(options) = &self.options {
127 tokenizer = tokenizer.with_unescape(options.unescape);
128 }
129 let tokens = tokenizer.tokenize()?;
130 self.new_parser(dialect)
131 .with_tokens(tokens)
132 .parse_statements()
133 })
134 }
137
138 pub fn one_statement_parses_to(&self, sql: &str, canonical: &str) -> Statement {
157 let mut statements = self.parse_sql_statements(sql).expect(sql);
158 match (&statements.len(), &1) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(statements.len(), 1);
159 if !canonical.is_empty() && sql != canonical {
160 match (&self.parse_sql_statements(canonical).unwrap(), &statements) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(self.parse_sql_statements(canonical).unwrap(), statements);
161 }
162
163 let only_statement = statements.pop().unwrap();
164
165 if !canonical.is_empty() {
166 match (&canonical, &only_statement.to_string()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
}assert_eq!(canonical, only_statement.to_string())
167 }
168 only_statement
169 }
170
171 pub fn statements_parse_to(&self, sql: &str, canonical: &str) -> Vec<Statement> {
173 let statements = self.parse_sql_statements(sql).expect(sql);
174 if !canonical.is_empty() && sql != canonical {
175 match (&self.parse_sql_statements(canonical).unwrap(), &statements) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(self.parse_sql_statements(canonical).unwrap(), statements);
176 } else {
177 match (&sql,
&statements.iter().map(|s|
s.to_string()).collect::<Vec<_>>().join("; ")) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
178 sql,
179 statements
180 .iter()
181 .map(|s| s.to_string())
182 .collect::<Vec<_>>()
183 .join("; ")
184 );
185 }
186 statements
187 }
188
189 pub fn expr_parses_to(&self, sql: &str, canonical: &str) -> Expr {
192 let ast = self
193 .run_parser_method(sql, |parser| parser.parse_expr())
194 .unwrap();
195 match (&canonical, &&ast.to_string()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(canonical, &ast.to_string());
196 ast
197 }
198
199 pub fn verified_stmt(&self, sql: &str) -> Statement {
203 self.one_statement_parses_to(sql, sql)
204 }
205
206 pub fn verified_query(&self, sql: &str) -> Query {
210 match self.verified_stmt(sql) {
211 Statement::Query(query) => *query,
212 _ => { ::core::panicking::panic_fmt(format_args!("Expected Query")); }panic!("Expected Query"),
213 }
214 }
215
216 pub fn verified_query_with_canonical(&self, query: &str, canonical: &str) -> Query {
220 match self.one_statement_parses_to(query, canonical) {
221 Statement::Query(query) => *query,
222 _ => { ::core::panicking::panic_fmt(format_args!("Expected Query")); }panic!("Expected Query"),
223 }
224 }
225
226 pub fn verified_only_select(&self, query: &str) -> Select {
230 match *self.verified_query(query).body {
231 SetExpr::Select(s) => *s,
232 _ => { ::core::panicking::panic_fmt(format_args!("Expected SetExpr::Select")); }panic!("Expected SetExpr::Select"),
233 }
234 }
235
236 pub fn verified_only_select_with_canonical(&self, query: &str, canonical: &str) -> Select {
244 let q = match self.one_statement_parses_to(query, canonical) {
245 Statement::Query(query) => *query,
246 _ => { ::core::panicking::panic_fmt(format_args!("Expected Query")); }panic!("Expected Query"),
247 };
248 match *q.body {
249 SetExpr::Select(s) => *s,
250 _ => { ::core::panicking::panic_fmt(format_args!("Expected SetExpr::Select")); }panic!("Expected SetExpr::Select"),
251 }
252 }
253
254 pub fn verified_expr(&self, sql: &str) -> Expr {
258 self.expr_parses_to(sql, sql)
259 }
260
261 pub fn tokenizes_to(&self, sql: &str, expected: Vec<Token>) {
263 if self.dialects.is_empty() {
264 { ::core::panicking::panic_fmt(format_args!("No dialects to test")); };panic!("No dialects to test");
265 }
266
267 self.dialects.iter().for_each(|dialect| {
268 let mut tokenizer = Tokenizer::new(&**dialect, sql);
269 if let Some(options) = &self.options {
270 tokenizer = tokenizer.with_unescape(options.unescape);
271 }
272 let tokens = tokenizer.tokenize().unwrap();
273 match (&expected, &tokens) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::Some(format_args!("Tokenized differently for {0:?}",
dialect)));
}
}
};assert_eq!(expected, tokens, "Tokenized differently for {dialect:?}");
274 });
275 }
276}
277
278pub fn all_dialects() -> TestedDialects {
280 TestedDialects::new(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Box::new(GenericDialect {}), Box::new(PostgreSqlDialect {}),
Box::new(MsSqlDialect {}), Box::new(AnsiDialect {}),
Box::new(SnowflakeDialect {}), Box::new(HiveDialect {}),
Box::new(RedshiftSqlDialect {}), Box::new(MySqlDialect {}),
Box::new(BigQueryDialect {}), Box::new(SQLiteDialect {}),
Box::new(DuckDbDialect {}), Box::new(DatabricksDialect {}),
Box::new(ClickHouseDialect {}), Box::new(OracleDialect {})]))vec![
281 Box::new(GenericDialect {}),
282 Box::new(PostgreSqlDialect {}),
283 Box::new(MsSqlDialect {}),
284 Box::new(AnsiDialect {}),
285 Box::new(SnowflakeDialect {}),
286 Box::new(HiveDialect {}),
287 Box::new(RedshiftSqlDialect {}),
288 Box::new(MySqlDialect {}),
289 Box::new(BigQueryDialect {}),
290 Box::new(SQLiteDialect {}),
291 Box::new(DuckDbDialect {}),
292 Box::new(DatabricksDialect {}),
293 Box::new(ClickHouseDialect {}),
294 Box::new(OracleDialect {}),
295 ])
296}
297
298pub fn all_dialects_with_options(options: ParserOptions) -> TestedDialects {
300 TestedDialects::new_with_options(all_dialects().dialects, options)
301}
302
303pub fn all_dialects_where<F>(predicate: F) -> TestedDialects
305where
306 F: Fn(&dyn Dialect) -> bool,
307{
308 let mut dialects = all_dialects();
309 dialects.dialects.retain(|d| predicate(&**d));
310 dialects
311}
312
313pub fn all_dialects_except<F>(except: F) -> TestedDialects
316where
317 F: Fn(&dyn Dialect) -> bool,
318{
319 all_dialects_where(|d| !except(d))
320}
321
322pub fn assert_eq_vec<T: ToString>(expected: &[&str], actual: &[T]) {
323 match (&expected, &actual.iter().map(ToString::to_string).collect::<Vec<_>>())
{
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
324 expected,
325 actual.iter().map(ToString::to_string).collect::<Vec<_>>()
326 );
327}
328
329pub fn only<T>(v: impl IntoIterator<Item = T>) -> T {
330 let mut iter = v.into_iter();
331 if let (Some(item), None) = (iter.next(), iter.next()) {
332 item
333 } else {
334 {
::core::panicking::panic_fmt(format_args!("only called on collection without exactly one item"));
}panic!("only called on collection without exactly one item")
335 }
336}
337
338pub fn expr_from_projection(item: &SelectItem) -> &Expr {
339 match item {
340 SelectItem::UnnamedExpr(expr) => expr,
341 _ => { ::core::panicking::panic_fmt(format_args!("Expected UnnamedExpr")); }panic!("Expected UnnamedExpr"),
342 }
343}
344
345pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTableOperation {
346 match stmt {
347 Statement::AlterTable(alter_table) => {
348 match (&alter_table.name.to_string(), &expected_name) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(alter_table.name.to_string(), expected_name);
349 if !!alter_table.if_exists {
::core::panicking::panic("assertion failed: !alter_table.if_exists")
};assert!(!alter_table.if_exists);
350 if !!alter_table.only {
::core::panicking::panic("assertion failed: !alter_table.only")
};assert!(!alter_table.only);
351 match (&alter_table.table_type, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(alter_table.table_type, None);
352 only(alter_table.operations)
353 }
354 _ => {
::core::panicking::panic_fmt(format_args!("Expected ALTER TABLE statement"));
}panic!("Expected ALTER TABLE statement"),
355 }
356}
357
358pub fn alter_table_op(stmt: Statement) -> AlterTableOperation {
359 alter_table_op_with_name(stmt, "tab")
360}
361
362pub fn number(n: &str) -> Value {
364 Value::Number(n.parse().unwrap(), false)
365}
366
367pub fn single_quoted_string(s: impl Into<String>) -> Value {
369 Value::SingleQuotedString(s.into())
370}
371
372pub fn table_alias(explicit: bool, name: impl Into<String>) -> Option<TableAlias> {
373 Some(TableAlias {
374 explicit,
375 name: Ident::new(name),
376 columns: ::alloc::vec::Vec::new()vec![],
377 })
378}
379
380pub fn table(name: impl Into<String>) -> TableFactor {
381 TableFactor::Table {
382 name: ObjectName::from(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Ident::new(name.into())]))vec![Ident::new(name.into())]),
383 alias: None,
384 args: None,
385 with_hints: ::alloc::vec::Vec::new()vec![],
386 version: None,
387 partitions: ::alloc::vec::Vec::new()vec![],
388 with_ordinality: false,
389 json_path: None,
390 sample: None,
391 index_hints: ::alloc::vec::Vec::new()vec![],
392 }
393}
394
395pub fn table_from_name(name: ObjectName) -> TableFactor {
396 TableFactor::Table {
397 name,
398 alias: None,
399 args: None,
400 with_hints: ::alloc::vec::Vec::new()vec![],
401 version: None,
402 partitions: ::alloc::vec::Vec::new()vec![],
403 with_ordinality: false,
404 json_path: None,
405 sample: None,
406 index_hints: ::alloc::vec::Vec::new()vec![],
407 }
408}
409
410pub fn table_with_alias(
411 name: impl Into<String>,
412 with_as_keyword: bool,
413 alias: impl Into<String>,
414) -> TableFactor {
415 TableFactor::Table {
416 name: ObjectName::from(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Ident::new(name)]))vec![Ident::new(name)]),
417 alias: table_alias(with_as_keyword, alias),
418 args: None,
419 with_hints: ::alloc::vec::Vec::new()vec![],
420 version: None,
421 partitions: ::alloc::vec::Vec::new()vec![],
422 with_ordinality: false,
423 json_path: None,
424 sample: None,
425 index_hints: ::alloc::vec::Vec::new()vec![],
426 }
427}
428
429pub fn join(relation: TableFactor) -> Join {
430 Join {
431 relation,
432 global: false,
433 join_operator: JoinOperator::Join(JoinConstraint::Natural),
434 }
435}
436
437pub fn call(function: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
438 Expr::Function(Function {
439 name: ObjectName::from(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Ident::new(function)]))vec![Ident::new(function)]),
440 uses_odbc_syntax: false,
441 parameters: FunctionArguments::None,
442 args: FunctionArguments::List(FunctionArgumentList {
443 duplicate_treatment: None,
444 args: args
445 .into_iter()
446 .map(|arg| FunctionArg::Unnamed(FunctionArgExpr::Expr(arg)))
447 .collect(),
448 clauses: ::alloc::vec::Vec::new()vec![],
449 }),
450 filter: None,
451 null_treatment: None,
452 over: None,
453 within_group: ::alloc::vec::Vec::new()vec![],
454 })
455}
456
457pub fn index_column(stmt: Statement) -> Expr {
460 match stmt {
461 Statement::CreateIndex(CreateIndex { columns, .. }) => {
462 columns.first().unwrap().column.expr.clone()
463 }
464 Statement::CreateTable(CreateTable { constraints, .. }) => {
465 match constraints.first().unwrap() {
466 TableConstraint::Index(constraint) => {
467 constraint.columns.first().unwrap().column.expr.clone()
468 }
469 TableConstraint::Unique(constraint) => {
470 constraint.columns.first().unwrap().column.expr.clone()
471 }
472 TableConstraint::PrimaryKey(constraint) => {
473 constraint.columns.first().unwrap().column.expr.clone()
474 }
475 TableConstraint::FulltextOrSpatial(constraint) => {
476 constraint.columns.first().unwrap().column.expr.clone()
477 }
478 _ => {
::core::panicking::panic_fmt(format_args!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"));
}panic!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"),
479 }
480 }
481 Statement::AlterTable(alter_table) => match alter_table.operations.first().unwrap() {
482 AlterTableOperation::AddConstraint { constraint, .. } => {
483 match constraint {
484 TableConstraint::Index(constraint) => {
485 constraint.columns.first().unwrap().column.expr.clone()
486 }
487 TableConstraint::Unique(constraint) => {
488 constraint.columns.first().unwrap().column.expr.clone()
489 }
490 TableConstraint::PrimaryKey(constraint) => {
491 constraint.columns.first().unwrap().column.expr.clone()
492 }
493 TableConstraint::FulltextOrSpatial(constraint) => {
494 constraint.columns.first().unwrap().column.expr.clone()
495 }
496 _ => {
::core::panicking::panic_fmt(format_args!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"));
}panic!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"),
497 }
498 }
499 _ => { ::core::panicking::panic_fmt(format_args!("Expected a constraint")); }panic!("Expected a constraint"),
500 },
501 _ => {
::core::panicking::panic_fmt(format_args!("Expected CREATE INDEX, ALTER TABLE, or CREATE TABLE, got: {0:?}",
stmt));
}panic!("Expected CREATE INDEX, ALTER TABLE, or CREATE TABLE, got: {stmt:?}"),
502 }
503}