sqlparser/dialect/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18mod ansi;
19mod bigquery;
20mod clickhouse;
21mod databricks;
22mod duckdb;
23mod generic;
24mod hive;
25mod mssql;
26mod mysql;
27mod oracle;
28mod postgresql;
29mod redshift;
30mod snowflake;
31mod sqlite;
32
33use core::any::{Any, TypeId};
34use core::fmt::Debug;
35use core::iter::Peekable;
36use core::str::Chars;
37
38use log::debug;
39
40pub use self::ansi::AnsiDialect;
41pub use self::bigquery::BigQueryDialect;
42pub use self::clickhouse::ClickHouseDialect;
43pub use self::databricks::DatabricksDialect;
44pub use self::duckdb::DuckDbDialect;
45pub use self::generic::GenericDialect;
46pub use self::hive::HiveDialect;
47pub use self::mssql::MsSqlDialect;
48pub use self::mysql::MySqlDialect;
49pub use self::oracle::OracleDialect;
50pub use self::postgresql::PostgreSqlDialect;
51pub use self::redshift::RedshiftSqlDialect;
52pub use self::snowflake::SnowflakeDialect;
53pub use self::sqlite::SQLiteDialect;
54use crate::ast::{ColumnOption, Expr, GranteesType, Ident, ObjectNamePart, Statement};
55pub use crate::keywords;
56use crate::keywords::Keyword;
57use crate::parser::{Parser, ParserError};
58use crate::tokenizer::Token;
59
60#[cfg(not(feature = "std"))]
61use alloc::boxed::Box;
62
63/// Convenience check if a [`Parser`] uses a certain dialect.
64///
65/// Note: when possible please the new style, adding a method to the [`Dialect`]
66/// trait rather than using this macro.
67///
68/// The benefits of adding a method on `Dialect` over this macro are:
69/// 1. user defined [`Dialect`]s can customize the parsing behavior
70/// 2. The differences between dialects can be clearly documented in the trait
71///
72/// `dialect_of!(parser is SQLiteDialect |  GenericDialect)` evaluates
73/// to `true` if `parser.dialect` is one of the [`Dialect`]s specified.
74macro_rules! dialect_of {
75    ( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
76        ($($parsed_dialect.dialect.is::<$dialect_type>())||+)
77    };
78}
79
80// Similar to above, but for applying directly against an instance of dialect
81// instead of a struct member named dialect. This avoids lifetime issues when
82// mixing match guards and token references.
83macro_rules! dialect_is {
84    ($dialect:ident is $($dialect_type:ty)|+) => {
85        ($($dialect.is::<$dialect_type>())||+)
86    }
87}
88
89/// Encapsulates the differences between SQL implementations.
90///
91/// # SQL Dialects
92///
93/// SQL implementations deviate from one another, either due to
94/// custom extensions or various historical reasons. This trait
95/// encapsulates the parsing differences between dialects.
96///
97/// [`GenericDialect`] is the most permissive dialect, and parses the union of
98/// all the other dialects, when there is no ambiguity. However, it does not
99/// currently allow `CREATE TABLE` statements without types specified for all
100/// columns; use [`SQLiteDialect`] if you require that.
101///
102/// # Examples
103/// Most users create a [`Dialect`] directly, as shown on the [module
104/// level documentation]:
105///
106/// ```
107/// # use sqlparser::dialect::AnsiDialect;
108/// let dialect = AnsiDialect {};
109/// ```
110///
111/// It is also possible to dynamically create a [`Dialect`] from its
112/// name. For example:
113///
114/// ```
115/// # use sqlparser::dialect::{AnsiDialect, dialect_from_str};
116/// let dialect = dialect_from_str("ansi").unwrap();
117///
118/// // Parsed dialect is an instance of `AnsiDialect`:
119/// assert!(dialect.is::<AnsiDialect>());
120/// ```
121///
122/// [module level documentation]: crate
123pub trait Dialect: Debug + Any {
124    /// Determine the [`TypeId`] of this dialect.
125    ///
126    /// By default, return the same [`TypeId`] as [`Any::type_id`]. Can be overridden
127    /// by dialects that behave like other dialects
128    /// (for example when wrapping a dialect).
129    fn dialect(&self) -> TypeId {
130        self.type_id()
131    }
132
133    /// Determine if a character starts a quoted identifier. The default
134    /// implementation, accepting "double quoted" ids is both ANSI-compliant
135    /// and appropriate for most dialects (with the notable exception of
136    /// MySQL, MS SQL, and sqlite). You can accept one of characters listed
137    /// in `Word::matching_end_quote` here
138    fn is_delimited_identifier_start(&self, ch: char) -> bool {
139        ch == '"' || ch == '`'
140    }
141
142    /// Determine if a character starts a potential nested quoted identifier.
143    /// Example: RedShift supports the following quote styles to all mean the same thing:
144    /// ```sql
145    /// SELECT 1 AS foo;
146    /// SELECT 1 AS "foo";
147    /// SELECT 1 AS [foo];
148    /// SELECT 1 AS ["foo"];
149    /// ```
150    fn is_nested_delimited_identifier_start(&self, _ch: char) -> bool {
151        false
152    }
153
154    /// Only applicable whenever [`Self::is_nested_delimited_identifier_start`] returns true
155    /// If the next sequence of tokens potentially represent a nested identifier, then this method
156    /// returns a tuple containing the outer quote style, and if present, the inner (nested) quote style.
157    ///
158    /// Example (Redshift):
159    /// ```text
160    /// `["foo"]` => Some(`[`, Some(`"`))
161    /// `[foo]` => Some(`[`, None)
162    /// `[0]` => None
163    /// `"foo"` => None
164    /// ```
165    fn peek_nested_delimited_identifier_quotes(
166        &self,
167        mut _chars: Peekable<Chars<'_>>,
168    ) -> Option<(char, Option<char>)> {
169        None
170    }
171
172    /// Return the character used to quote identifiers.
173    fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
174        None
175    }
176
177    /// Determine if a character is a valid start character for an unquoted identifier
178    fn is_identifier_start(&self, ch: char) -> bool;
179
180    /// Determine if a character is a valid unquoted identifier character
181    fn is_identifier_part(&self, ch: char) -> bool;
182
183    /// Most dialects do not have custom operators. Override this method to provide custom operators.
184    fn is_custom_operator_part(&self, _ch: char) -> bool {
185        false
186    }
187
188    /// Determine if the dialect supports escaping characters via '\' in string literals.
189    ///
190    /// Some dialects like BigQuery and Snowflake support this while others like
191    /// Postgres do not. Such that the following is accepted by the former but
192    /// rejected by the latter.
193    /// ```sql
194    /// SELECT 'ab\'cd';
195    /// ```
196    ///
197    /// Conversely, such dialects reject the following statement which
198    /// otherwise would be valid in the other dialects.
199    /// ```sql
200    /// SELECT '\';
201    /// ```
202    fn supports_string_literal_backslash_escape(&self) -> bool {
203        false
204    }
205
206    /// Determine whether the dialect strips the backslash when escaping LIKE wildcards (%, _).
207    ///
208    /// [MySQL] has a special case when escaping single quoted strings which leaves these unescaped
209    /// so they can be used in LIKE patterns without double-escaping (as is necessary in other
210    /// escaping dialects, such as [Snowflake]). Generally, special characters have escaping rules
211    /// causing them to be replaced with a different byte sequences (e.g. `'\0'` becoming the zero
212    /// byte), and the default if an escaped character does not have a specific escaping rule is to
213    /// strip the backslash (e.g. there is no rule for `h`, so `'\h' = 'h'`). MySQL's special case
214    /// for ignoring LIKE wildcard escapes is to *not* strip the backslash, so that `'\%' = '\\%'`.
215    /// This applies to all string literals though, not just those used in LIKE patterns.
216    ///
217    /// ```text
218    /// mysql> select '\_', hex('\\'), hex('_'), hex('\_');
219    /// +----+-----------+----------+-----------+
220    /// | \_ | hex('\\') | hex('_') | hex('\_') |
221    /// +----+-----------+----------+-----------+
222    /// | \_ | 5C        | 5F       | 5C5F      |
223    /// +----+-----------+----------+-----------+
224    /// 1 row in set (0.00 sec)
225    /// ```
226    ///
227    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/string-literals.html
228    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/functions/like#usage-notes
229    fn ignores_wildcard_escapes(&self) -> bool {
230        false
231    }
232
233    /// Determine if the dialect supports string literals with `U&` prefix.
234    /// This is used to specify Unicode code points in string literals.
235    /// For example, in PostgreSQL, the following is a valid string literal:
236    /// ```sql
237    /// SELECT U&'\0061\0062\0063';
238    /// ```
239    /// This is equivalent to the string literal `'abc'`.
240    /// See
241    ///  - [Postgres docs](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE)
242    ///  - [H2 docs](http://www.h2database.com/html/grammar.html#string)
243    fn supports_unicode_string_literal(&self) -> bool {
244        false
245    }
246
247    /// Does the dialect support `FILTER (WHERE expr)` for aggregate queries?
248    fn supports_filter_during_aggregation(&self) -> bool {
249        false
250    }
251
252    /// Returns true if the dialect supports referencing another named window
253    /// within a window clause declaration.
254    ///
255    /// Example
256    /// ```sql
257    /// SELECT * FROM mytable
258    /// WINDOW mynamed_window AS another_named_window
259    /// ```
260    fn supports_window_clause_named_window_reference(&self) -> bool {
261        false
262    }
263
264    /// Returns true if the dialect supports `ARRAY_AGG() [WITHIN GROUP (ORDER BY)]` expressions.
265    /// Otherwise, the dialect should expect an `ORDER BY` without the `WITHIN GROUP` clause, e.g. [`ANSI`]
266    ///
267    /// [`ANSI`]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#array-aggregate-function
268    fn supports_within_after_array_aggregation(&self) -> bool {
269        false
270    }
271
272    /// Returns true if the dialects supports `group sets, roll up, or cube` expressions.
273    fn supports_group_by_expr(&self) -> bool {
274        false
275    }
276
277    /// Returns true if the dialects supports `GROUP BY` modifiers prefixed by a `WITH` keyword.
278    /// Example: `GROUP BY value WITH ROLLUP`.
279    fn supports_group_by_with_modifier(&self) -> bool {
280        false
281    }
282
283    /// Indicates whether the dialect supports left-associative join parsing
284    /// by default when parentheses are omitted in nested joins.
285    ///
286    /// Most dialects (like MySQL or Postgres) assume **left-associative** precedence,
287    /// so a query like:
288    ///
289    /// ```sql
290    /// SELECT * FROM t1 NATURAL JOIN t5 INNER JOIN t0 ON ...
291    /// ```
292    /// is interpreted as:
293    /// ```sql
294    /// ((t1 NATURAL JOIN t5) INNER JOIN t0 ON ...)
295    /// ```
296    /// and internally represented as a **flat list** of joins.
297    ///
298    /// In contrast, some dialects (e.g. **Snowflake**) assume **right-associative**
299    /// precedence and interpret the same query as:
300    /// ```sql
301    /// (t1 NATURAL JOIN (t5 INNER JOIN t0 ON ...))
302    /// ```
303    /// which results in a **nested join** structure in the AST.
304    ///
305    /// If this method returns `false`, the parser must build nested join trees
306    /// even in the absence of parentheses to reflect the correct associativity
307    fn supports_left_associative_joins_without_parens(&self) -> bool {
308        true
309    }
310
311    /// Returns true if the dialect supports the `(+)` syntax for OUTER JOIN.
312    fn supports_outer_join_operator(&self) -> bool {
313        false
314    }
315
316    /// Returns true if the dialect supports a join specification on CROSS JOIN.
317    fn supports_cross_join_constraint(&self) -> bool {
318        false
319    }
320
321    /// Returns true if the dialect supports CONNECT BY.
322    fn supports_connect_by(&self) -> bool {
323        false
324    }
325
326    /// Returns true if the dialect supports `EXECUTE IMMEDIATE` statements.
327    fn supports_execute_immediate(&self) -> bool {
328        false
329    }
330
331    /// Returns true if the dialect supports the MATCH_RECOGNIZE operation.
332    fn supports_match_recognize(&self) -> bool {
333        false
334    }
335
336    /// Returns true if the dialect supports `(NOT) IN ()` expressions
337    fn supports_in_empty_list(&self) -> bool {
338        false
339    }
340
341    /// Returns true if the dialect supports `BEGIN {DEFERRED | IMMEDIATE | EXCLUSIVE | TRY | CATCH} [TRANSACTION]` statements
342    fn supports_start_transaction_modifier(&self) -> bool {
343        false
344    }
345
346    /// Returns true if the dialect supports `END {TRY | CATCH}` statements
347    fn supports_end_transaction_modifier(&self) -> bool {
348        false
349    }
350
351    /// Returns true if the dialect supports named arguments of the form `FUN(a = '1', b = '2')`.
352    fn supports_named_fn_args_with_eq_operator(&self) -> bool {
353        false
354    }
355
356    /// Returns true if the dialect supports named arguments of the form `FUN(a : '1', b : '2')`.
357    fn supports_named_fn_args_with_colon_operator(&self) -> bool {
358        false
359    }
360
361    /// Returns true if the dialect supports named arguments of the form `FUN(a := '1', b := '2')`.
362    fn supports_named_fn_args_with_assignment_operator(&self) -> bool {
363        false
364    }
365
366    /// Returns true if the dialect supports named arguments of the form `FUN(a => '1', b => '2')`.
367    fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
368        true
369    }
370
371    /// Returns true if dialect supports argument name as arbitrary expression.
372    /// e.g. `FUN(LOWER('a'):'1',  b:'2')`
373    /// Such function arguments are represented in the AST by the `FunctionArg::ExprNamed` variant,
374    /// otherwise use the `FunctionArg::Named` variant (compatible reason).
375    fn supports_named_fn_args_with_expr_name(&self) -> bool {
376        false
377    }
378
379    /// Returns true if the dialect supports identifiers starting with a numeric
380    /// prefix such as tables named `59901_user_login`
381    fn supports_numeric_prefix(&self) -> bool {
382        false
383    }
384
385    /// Returns true if the dialect supports numbers containing underscores, e.g. `10_000_000`
386    fn supports_numeric_literal_underscores(&self) -> bool {
387        false
388    }
389
390    /// Returns true if the dialects supports specifying null treatment
391    /// as part of a window function's parameter list as opposed
392    /// to after the parameter list.
393    ///
394    /// i.e The following syntax returns true
395    /// ```sql
396    /// FIRST_VALUE(a IGNORE NULLS) OVER ()
397    /// ```
398    /// while the following syntax returns false
399    /// ```sql
400    /// FIRST_VALUE(a) IGNORE NULLS OVER ()
401    /// ```
402    fn supports_window_function_null_treatment_arg(&self) -> bool {
403        false
404    }
405
406    /// Returns true if the dialect supports defining structs or objects using a
407    /// syntax like `{'x': 1, 'y': 2, 'z': 3}`.
408    fn supports_dictionary_syntax(&self) -> bool {
409        false
410    }
411
412    /// Returns true if the dialect supports defining object using the
413    /// syntax like `Map {1: 10, 2: 20}`.
414    fn support_map_literal_syntax(&self) -> bool {
415        false
416    }
417
418    /// Returns true if the dialect supports lambda functions, for example:
419    ///
420    /// ```sql
421    /// SELECT transform(array(1, 2, 3), x -> x + 1); -- returns [2,3,4]
422    /// ```
423    fn supports_lambda_functions(&self) -> bool {
424        false
425    }
426
427    /// Returns true if the dialect supports multiple variable assignment
428    /// using parentheses in a `SET` variable declaration.
429    ///
430    /// ```sql
431    /// SET (variable[, ...]) = (expression[, ...]);
432    /// ```
433    fn supports_parenthesized_set_variables(&self) -> bool {
434        false
435    }
436
437    /// Returns true if the dialect supports multiple `SET` statements
438    /// in a single statement.
439    ///
440    /// ```sql
441    /// SET variable = expression [, variable = expression];
442    /// ```
443    fn supports_comma_separated_set_assignments(&self) -> bool {
444        false
445    }
446
447    /// Returns true if the dialect supports an `EXCEPT` clause following a
448    /// wildcard in a select list.
449    ///
450    /// For example
451    /// ```sql
452    /// SELECT * EXCEPT order_id FROM orders;
453    /// ```
454    fn supports_select_wildcard_except(&self) -> bool {
455        false
456    }
457
458    /// Returns true if the dialect has a CONVERT function which accepts a type first
459    /// and an expression second, e.g. `CONVERT(varchar, 1)`
460    fn convert_type_before_value(&self) -> bool {
461        false
462    }
463
464    /// Returns true if the dialect supports triple quoted string
465    /// e.g. `"""abc"""`
466    fn supports_triple_quoted_string(&self) -> bool {
467        false
468    }
469
470    /// Dialect-specific prefix parser override
471    fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
472        // return None to fall back to the default behavior
473        None
474    }
475
476    /// Does the dialect support trailing commas around the query?
477    fn supports_trailing_commas(&self) -> bool {
478        false
479    }
480
481    /// Does the dialect support parsing `LIMIT 1, 2` as `LIMIT 2 OFFSET 1`?
482    fn supports_limit_comma(&self) -> bool {
483        false
484    }
485
486    /// Returns true if the dialect supports concatenating of string literal
487    /// Example: `SELECT 'Hello ' "world" => SELECT 'Hello world'`
488    fn supports_string_literal_concatenation(&self) -> bool {
489        false
490    }
491
492    /// Does the dialect support trailing commas in the projection list?
493    fn supports_projection_trailing_commas(&self) -> bool {
494        self.supports_trailing_commas()
495    }
496
497    /// Returns true if the dialect supports trailing commas in the `FROM` clause of a `SELECT` statement.
498    /// Example: `SELECT 1 FROM T, U, LIMIT 1`
499    fn supports_from_trailing_commas(&self) -> bool {
500        false
501    }
502
503    /// Returns true if the dialect supports trailing commas in the
504    /// column definitions list of a `CREATE` statement.
505    /// Example: `CREATE TABLE T (x INT, y TEXT,)`
506    fn supports_column_definition_trailing_commas(&self) -> bool {
507        false
508    }
509
510    /// Returns true if the dialect supports double dot notation for object names
511    ///
512    /// Example
513    /// ```sql
514    /// SELECT * FROM db_name..table_name
515    /// ```
516    fn supports_object_name_double_dot_notation(&self) -> bool {
517        false
518    }
519
520    /// Return true if the dialect supports the STRUCT literal
521    ///
522    /// Example
523    /// ```sql
524    /// SELECT STRUCT(1 as one, 'foo' as foo, false)
525    /// ```
526    fn supports_struct_literal(&self) -> bool {
527        false
528    }
529
530    /// Return true if the dialect supports empty projections in SELECT statements
531    ///
532    /// Example
533    /// ```sql
534    /// SELECT from table_name
535    /// ```
536    fn supports_empty_projections(&self) -> bool {
537        false
538    }
539
540    /// Return true if the dialect supports wildcard expansion on
541    /// arbitrary expressions in projections.
542    ///
543    /// Example:
544    /// ```sql
545    /// SELECT STRUCT<STRING>('foo').* FROM T
546    /// ```
547    fn supports_select_expr_star(&self) -> bool {
548        false
549    }
550
551    /// Return true if the dialect supports "FROM-first" selects.
552    ///
553    /// Example:
554    /// ```sql
555    /// FROM table
556    /// SELECT *
557    /// ```
558    fn supports_from_first_select(&self) -> bool {
559        false
560    }
561
562    /// Return true if the dialect supports pipe operator.
563    ///
564    /// Example:
565    /// ```sql
566    /// SELECT *
567    /// FROM table
568    /// |> limit 1
569    /// ```
570    ///
571    /// See <https://cloud.google.com/bigquery/docs/pipe-syntax-guide#basic_syntax>
572    fn supports_pipe_operator(&self) -> bool {
573        false
574    }
575
576    /// Does the dialect support MySQL-style `'user'@'host'` grantee syntax?
577    fn supports_user_host_grantee(&self) -> bool {
578        false
579    }
580
581    /// Does the dialect support the `MATCH() AGAINST()` syntax?
582    fn supports_match_against(&self) -> bool {
583        false
584    }
585
586    /// Returns true if the dialect supports an exclude option
587    /// following a wildcard in the projection section. For example:
588    /// `SELECT * EXCLUDE col1 FROM tbl`.
589    ///
590    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_EXCLUDE_list.html)
591    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select)
592    fn supports_select_wildcard_exclude(&self) -> bool {
593        false
594    }
595
596    /// Returns true if the dialect supports an exclude option
597    /// as the last item in the projection section, not necessarily
598    /// after a wildcard. For example:
599    /// `SELECT *, c1, c2 EXCLUDE c3 FROM tbl`
600    ///
601    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_EXCLUDE_list.html)
602    fn supports_select_exclude(&self) -> bool {
603        false
604    }
605
606    /// Returns true if the dialect supports specifying multiple options
607    /// in a `CREATE TABLE` statement for the structure of the new table. For example:
608    /// `CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a`
609    fn supports_create_table_multi_schema_info_sources(&self) -> bool {
610        false
611    }
612
613    /// Dialect-specific infix parser override
614    ///
615    /// This method is called to parse the next infix expression.
616    ///
617    /// If `None` is returned, falls back to the default behavior.
618    fn parse_infix(
619        &self,
620        _parser: &mut Parser,
621        _expr: &Expr,
622        _precedence: u8,
623    ) -> Option<Result<Expr, ParserError>> {
624        // return None to fall back to the default behavior
625        None
626    }
627
628    /// Dialect-specific precedence override
629    ///
630    /// This method is called to get the precedence of the next token.
631    ///
632    /// If `None` is returned, falls back to the default behavior.
633    fn get_next_precedence(&self, _parser: &Parser) -> Option<Result<u8, ParserError>> {
634        // return None to fall back to the default behavior
635        None
636    }
637
638    /// Get the precedence of the next token, looking at the full token stream.
639    ///
640    /// A higher number => higher precedence
641    ///
642    /// See [`Self::get_next_precedence`] to override the behavior for just the
643    /// next token.
644    ///
645    /// The default implementation is used for many dialects, but can be
646    /// overridden to provide dialect-specific behavior.
647    fn get_next_precedence_default(&self, parser: &Parser) -> Result<u8, ParserError> {
648        if let Some(precedence) = self.get_next_precedence(parser) {
649            return precedence;
650        }
651        macro_rules! p {
652            ($precedence:ident) => {
653                self.prec_value(Precedence::$precedence)
654            };
655        }
656
657        let token = parser.peek_token();
658        debug!("get_next_precedence_full() {token:?}");
659        match token.token {
660            Token::Word(w) if w.keyword == Keyword::OR => Ok(p!(Or)),
661            Token::Word(w) if w.keyword == Keyword::AND => Ok(p!(And)),
662            Token::Word(w) if w.keyword == Keyword::XOR => Ok(p!(Xor)),
663
664            Token::Word(w) if w.keyword == Keyword::AT => {
665                match (
666                    parser.peek_nth_token(1).token,
667                    parser.peek_nth_token(2).token,
668                ) {
669                    (Token::Word(w), Token::Word(w2))
670                        if w.keyword == Keyword::TIME && w2.keyword == Keyword::ZONE =>
671                    {
672                        Ok(p!(AtTz))
673                    }
674                    _ => Ok(self.prec_unknown()),
675                }
676            }
677
678            Token::Word(w) if w.keyword == Keyword::NOT => match parser.peek_nth_token(1).token {
679                // The precedence of NOT varies depending on keyword that
680                // follows it. If it is followed by IN, BETWEEN, or LIKE,
681                // it takes on the precedence of those tokens. Otherwise, it
682                // is not an infix operator, and therefore has zero
683                // precedence.
684                Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
685                Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
686                Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
687                Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
688                Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
689                Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
690                Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
691                Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
692                Token::Word(w) if w.keyword == Keyword::MEMBER => Ok(p!(Like)),
693                Token::Word(w)
694                    if w.keyword == Keyword::NULL && !parser.in_column_definition_state() =>
695                {
696                    Ok(p!(Is))
697                }
698                _ => Ok(self.prec_unknown()),
699            },
700            Token::Word(w) if w.keyword == Keyword::NOTNULL && self.supports_notnull_operator() => {
701                Ok(p!(Is))
702            }
703            Token::Word(w) if w.keyword == Keyword::IS => Ok(p!(Is)),
704            Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
705            Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
706            Token::Word(w) if w.keyword == Keyword::OVERLAPS => Ok(p!(Between)),
707            Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
708            Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
709            Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
710            Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
711            Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
712            Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
713            Token::Word(w) if w.keyword == Keyword::MEMBER => Ok(p!(Like)),
714            Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(p!(Between)),
715            Token::Word(w) if w.keyword == Keyword::DIV => Ok(p!(MulDivModOp)),
716            Token::Period => Ok(p!(Period)),
717            Token::Assignment
718            | Token::Eq
719            | Token::Lt
720            | Token::LtEq
721            | Token::Neq
722            | Token::Gt
723            | Token::GtEq
724            | Token::DoubleEq
725            | Token::Tilde
726            | Token::TildeAsterisk
727            | Token::ExclamationMarkTilde
728            | Token::ExclamationMarkTildeAsterisk
729            | Token::DoubleTilde
730            | Token::DoubleTildeAsterisk
731            | Token::ExclamationMarkDoubleTilde
732            | Token::ExclamationMarkDoubleTildeAsterisk
733            | Token::Spaceship => Ok(p!(Eq)),
734            Token::Pipe
735            | Token::QuestionMarkDash
736            | Token::DoubleSharp
737            | Token::Overlap
738            | Token::AmpersandLeftAngleBracket
739            | Token::AmpersandRightAngleBracket
740            | Token::QuestionMarkDashVerticalBar
741            | Token::AmpersandLeftAngleBracketVerticalBar
742            | Token::VerticalBarAmpersandRightAngleBracket
743            | Token::TwoWayArrow
744            | Token::LeftAngleBracketCaret
745            | Token::RightAngleBracketCaret
746            | Token::QuestionMarkSharp
747            | Token::QuestionMarkDoubleVerticalBar
748            | Token::QuestionPipe
749            | Token::TildeEqual
750            | Token::AtSign
751            | Token::ShiftLeftVerticalBar
752            | Token::VerticalBarShiftRight => Ok(p!(Pipe)),
753            Token::Caret | Token::Sharp | Token::ShiftRight | Token::ShiftLeft => Ok(p!(Caret)),
754            Token::Ampersand => Ok(p!(Ampersand)),
755            Token::Plus | Token::Minus => Ok(p!(PlusMinus)),
756            Token::Mul | Token::Div | Token::DuckIntDiv | Token::Mod | Token::StringConcat => {
757                Ok(p!(MulDivModOp))
758            }
759            Token::DoubleColon | Token::ExclamationMark | Token::LBracket | Token::CaretAt => {
760                Ok(p!(DoubleColon))
761            }
762            Token::Arrow
763            | Token::LongArrow
764            | Token::HashArrow
765            | Token::HashLongArrow
766            | Token::AtArrow
767            | Token::ArrowAt
768            | Token::HashMinus
769            | Token::AtQuestion
770            | Token::AtAt
771            | Token::Question
772            | Token::QuestionAnd
773            | Token::CustomBinaryOperator(_) => Ok(p!(PgOther)),
774            _ => Ok(self.prec_unknown()),
775        }
776    }
777
778    /// Dialect-specific statement parser override
779    ///
780    /// This method is called to parse the next statement.
781    ///
782    /// If `None` is returned, falls back to the default behavior.
783    fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
784        // return None to fall back to the default behavior
785        None
786    }
787
788    /// Dialect-specific column option parser override
789    ///
790    /// This method is called to parse the next column option.
791    ///
792    /// If `None` is returned, falls back to the default behavior.
793    fn parse_column_option(
794        &self,
795        _parser: &mut Parser,
796    ) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
797        // return None to fall back to the default behavior
798        Ok(None)
799    }
800
801    /// Decide the lexical Precedence of operators.
802    ///
803    /// Uses (APPROXIMATELY) <https://www.postgresql.org/docs/7.0/operators.htm#AEN2026> as a reference
804    fn prec_value(&self, prec: Precedence) -> u8 {
805        match prec {
806            Precedence::Period => 100,
807            Precedence::DoubleColon => 50,
808            Precedence::AtTz => 41,
809            Precedence::MulDivModOp => 40,
810            Precedence::PlusMinus => 30,
811            Precedence::Xor => 24,
812            Precedence::Ampersand => 23,
813            Precedence::Caret => 22,
814            Precedence::Pipe => 21,
815            Precedence::Between => 20,
816            Precedence::Eq => 20,
817            Precedence::Like => 19,
818            Precedence::Is => 17,
819            Precedence::PgOther => 16,
820            Precedence::UnaryNot => 15,
821            Precedence::And => 10,
822            Precedence::Or => 5,
823        }
824    }
825
826    /// Returns the precedence when the precedence is otherwise unknown
827    fn prec_unknown(&self) -> u8 {
828        0
829    }
830
831    /// Returns true if this dialect requires the `TABLE` keyword after `DESCRIBE`
832    ///
833    /// Defaults to false.
834    ///
835    /// If true, the following statement is valid: `DESCRIBE TABLE my_table`
836    /// If false, the following statements are valid: `DESCRIBE my_table` and `DESCRIBE table`
837    fn describe_requires_table_keyword(&self) -> bool {
838        false
839    }
840
841    /// Returns true if this dialect allows the `EXTRACT` function to words other than [`Keyword`].
842    fn allow_extract_custom(&self) -> bool {
843        false
844    }
845
846    /// Returns true if this dialect allows the `EXTRACT` function to use single quotes in the part being extracted.
847    fn allow_extract_single_quotes(&self) -> bool {
848        false
849    }
850
851    /// Returns true if this dialect allows dollar placeholders
852    /// e.g. `SELECT $var` (SQLite)
853    fn supports_dollar_placeholder(&self) -> bool {
854        false
855    }
856
857    /// Does the dialect support with clause in create index statement?
858    /// e.g. `CREATE INDEX idx ON t WITH (key = value, key2)`
859    fn supports_create_index_with_clause(&self) -> bool {
860        false
861    }
862
863    /// Whether `INTERVAL` expressions require units (called "qualifiers" in the ANSI SQL spec) to be specified,
864    /// e.g. `INTERVAL 1 DAY` vs `INTERVAL 1`.
865    ///
866    /// Expressions within intervals (e.g. `INTERVAL '1' + '1' DAY`) are only allowed when units are required.
867    ///
868    /// See <https://github.com/sqlparser-rs/sqlparser-rs/pull/1398> for more information.
869    ///
870    /// When `true`:
871    /// * `INTERVAL '1' DAY` is VALID
872    /// * `INTERVAL 1 + 1 DAY` is VALID
873    /// * `INTERVAL '1' + '1' DAY` is VALID
874    /// * `INTERVAL '1'` is INVALID
875    ///
876    /// When `false`:
877    /// * `INTERVAL '1'` is VALID
878    /// * `INTERVAL '1' DAY` is VALID — unit is not required, but still allowed
879    /// * `INTERVAL 1 + 1 DAY` is INVALID
880    fn require_interval_qualifier(&self) -> bool {
881        false
882    }
883
884    fn supports_explain_with_utility_options(&self) -> bool {
885        false
886    }
887
888    fn supports_asc_desc_in_column_definition(&self) -> bool {
889        false
890    }
891
892    /// Returns true if the dialect supports `a!` expressions
893    fn supports_factorial_operator(&self) -> bool {
894        false
895    }
896
897    /// Returns true if the dialect supports nested comments
898    /// e.g. `/* /* nested */ */`
899    fn supports_nested_comments(&self) -> bool {
900        false
901    }
902
903    /// Returns true if this dialect supports treating the equals operator `=` within a `SelectItem`
904    /// as an alias assignment operator, rather than a boolean expression.
905    /// For example: the following statements are equivalent for such a dialect:
906    /// ```sql
907    ///  SELECT col_alias = col FROM tbl;
908    ///  SELECT col_alias AS col FROM tbl;
909    /// ```
910    fn supports_eq_alias_assignment(&self) -> bool {
911        false
912    }
913
914    /// Returns true if this dialect supports the `TRY_CONVERT` function
915    fn supports_try_convert(&self) -> bool {
916        false
917    }
918
919    /// Returns true if the dialect supports `!a` syntax for boolean `NOT` expressions.
920    fn supports_bang_not_operator(&self) -> bool {
921        false
922    }
923
924    /// Returns true if the dialect supports the `LISTEN`, `UNLISTEN` and `NOTIFY` statements
925    fn supports_listen_notify(&self) -> bool {
926        false
927    }
928
929    /// Returns true if the dialect supports the `LOAD DATA` statement
930    fn supports_load_data(&self) -> bool {
931        false
932    }
933
934    /// Returns true if the dialect supports the `LOAD extension` statement
935    fn supports_load_extension(&self) -> bool {
936        false
937    }
938
939    /// Returns true if this dialect expects the `TOP` option
940    /// before the `ALL`/`DISTINCT` options in a `SELECT` statement.
941    fn supports_top_before_distinct(&self) -> bool {
942        false
943    }
944
945    /// Returns true if the dialect supports boolean literals (`true` and `false`).
946    /// For example, in MSSQL these are treated as identifiers rather than boolean literals.
947    fn supports_boolean_literals(&self) -> bool {
948        true
949    }
950
951    /// Returns true if this dialect supports the `LIKE 'pattern'` option in
952    /// a `SHOW` statement before the `IN` option
953    fn supports_show_like_before_in(&self) -> bool {
954        false
955    }
956
957    /// Returns true if this dialect supports the `COMMENT` statement
958    fn supports_comment_on(&self) -> bool {
959        false
960    }
961
962    /// Returns true if the dialect supports the `CREATE TABLE SELECT` statement
963    fn supports_create_table_select(&self) -> bool {
964        false
965    }
966
967    /// Returns true if the dialect supports PartiQL for querying semi-structured data
968    /// <https://partiql.org/index.html>
969    fn supports_partiql(&self) -> bool {
970        false
971    }
972
973    /// Returns true if the specified keyword is reserved and cannot be
974    /// used as an identifier without special handling like quoting.
975    fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
976        keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
977    }
978
979    /// Returns reserved keywords that may prefix a select item expression
980    /// e.g. `SELECT CONNECT_BY_ROOT name FROM Tbl2` (Snowflake)
981    fn get_reserved_keywords_for_select_item_operator(&self) -> &[Keyword] {
982        &[]
983    }
984
985    /// Returns grantee types that should be treated as identifiers
986    fn get_reserved_grantees_types(&self) -> &[GranteesType] {
987        &[]
988    }
989
990    /// Returns true if this dialect supports the `TABLESAMPLE` option
991    /// before the table alias option. For example:
992    ///
993    /// Table sample before alias: `SELECT * FROM tbl AS t TABLESAMPLE (10)`
994    /// Table sample after alias: `SELECT * FROM tbl TABLESAMPLE (10) AS t`
995    ///
996    /// <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#_7_6_table_reference>
997    fn supports_table_sample_before_alias(&self) -> bool {
998        false
999    }
1000
1001    /// Returns true if this dialect supports the `INSERT INTO ... SET col1 = 1, ...` syntax.
1002    ///
1003    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/insert.html>
1004    fn supports_insert_set(&self) -> bool {
1005        false
1006    }
1007
1008    /// Does the dialect support table function in insertion?
1009    fn supports_insert_table_function(&self) -> bool {
1010        false
1011    }
1012
1013    /// Does the dialect support insert formats, e.g. `INSERT INTO ... FORMAT <format>`
1014    fn supports_insert_format(&self) -> bool {
1015        false
1016    }
1017
1018    /// Returns true if this dialect supports `SET` statements without an explicit
1019    /// assignment operator such as `=`. For example: `SET SHOWPLAN_XML ON`.
1020    fn supports_set_stmt_without_operator(&self) -> bool {
1021        false
1022    }
1023
1024    /// Returns true if the specified keyword should be parsed as a column identifier.
1025    /// See [keywords::RESERVED_FOR_COLUMN_ALIAS]
1026    fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1027        !keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw)
1028    }
1029
1030    /// Returns true if the specified keyword should be parsed as a select item alias.
1031    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
1032    /// to enable looking ahead if needed.
1033    fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1034        explicit || self.is_column_alias(kw, parser)
1035    }
1036
1037    /// Returns true if the specified keyword should be parsed as a table factor identifier.
1038    /// See [keywords::RESERVED_FOR_TABLE_FACTOR]
1039    fn is_table_factor(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1040        !keywords::RESERVED_FOR_TABLE_FACTOR.contains(kw)
1041    }
1042
1043    /// Returns true if the specified keyword should be parsed as a table factor alias.
1044    /// See [keywords::RESERVED_FOR_TABLE_ALIAS]
1045    fn is_table_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1046        !keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
1047    }
1048
1049    /// Returns true if the specified keyword should be parsed as a table factor alias.
1050    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
1051    /// to enable looking ahead if needed.
1052    fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1053        explicit || self.is_table_alias(kw, parser)
1054    }
1055
1056    /// Returns true if this dialect supports querying historical table data
1057    /// by specifying which version of the data to query.
1058    fn supports_timestamp_versioning(&self) -> bool {
1059        false
1060    }
1061
1062    /// Returns true if this dialect supports the E'...' syntax for string literals
1063    ///
1064    /// Postgres: <https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE>
1065    fn supports_string_escape_constant(&self) -> bool {
1066        false
1067    }
1068
1069    /// Returns true if the dialect supports the table hints in the `FROM` clause.
1070    fn supports_table_hints(&self) -> bool {
1071        false
1072    }
1073
1074    /// Returns true if this dialect requires a whitespace character after `--` to start a single line comment.
1075    ///
1076    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/ansi-diff-comments.html>
1077    /// e.g. UPDATE account SET balance=balance--1
1078    //       WHERE account_id=5752             ^^^ will be interpreted as two minus signs instead of a comment
1079    fn requires_single_line_comment_whitespace(&self) -> bool {
1080        false
1081    }
1082
1083    /// Returns true if the dialect supports array type definition with brackets with
1084    /// an optional size. For example:
1085    /// ```CREATE TABLE my_table (arr1 INT[], arr2 INT[3])```
1086    /// ```SELECT x::INT[]```
1087    fn supports_array_typedef_with_brackets(&self) -> bool {
1088        false
1089    }
1090    /// Returns true if the dialect supports geometric types.
1091    ///
1092    /// Postgres: <https://www.postgresql.org/docs/9.5/functions-geometry.html>
1093    /// e.g. @@ circle '((0,0),10)'
1094    fn supports_geometric_types(&self) -> bool {
1095        false
1096    }
1097
1098    /// Returns true if the dialect supports `ORDER BY ALL`.
1099    /// `ALL` which means all columns of the SELECT clause.
1100    ///
1101    /// For example: ```SELECT * FROM addresses ORDER BY ALL;```.
1102    fn supports_order_by_all(&self) -> bool {
1103        false
1104    }
1105
1106    /// Returns true if the dialect supports `SET NAMES <charset_name> [COLLATE <collation_name>]`.
1107    ///
1108    /// - [MySQL](https://dev.mysql.com/doc/refman/8.4/en/set-names.html)
1109    /// - [PostgreSQL](https://www.postgresql.org/docs/17/sql-set.html)
1110    ///
1111    /// Note: Postgres doesn't support the `COLLATE` clause, but we permissively parse it anyway.
1112    fn supports_set_names(&self) -> bool {
1113        false
1114    }
1115
1116    fn supports_space_separated_column_options(&self) -> bool {
1117        false
1118    }
1119
1120    /// Returns true if the dialect supports the `USING` clause in an `ALTER COLUMN` statement.
1121    /// Example:
1122    ///  ```sql
1123    ///  ALTER TABLE tbl ALTER COLUMN col SET DATA TYPE <type> USING <exp>`
1124    /// ```
1125    fn supports_alter_column_type_using(&self) -> bool {
1126        false
1127    }
1128
1129    /// Returns true if the dialect supports `ALTER TABLE tbl DROP COLUMN c1, ..., cn`
1130    fn supports_comma_separated_drop_column_list(&self) -> bool {
1131        false
1132    }
1133
1134    /// Returns true if the dialect considers the specified ident as a function
1135    /// that returns an identifier. Typically used to generate identifiers
1136    /// programmatically.
1137    ///
1138    /// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
1139    fn is_identifier_generating_function_name(
1140        &self,
1141        _ident: &Ident,
1142        _name_parts: &[ObjectNamePart],
1143    ) -> bool {
1144        false
1145    }
1146
1147    /// Returns true if the dialect supports the `x NOTNULL`
1148    /// operator expression.
1149    fn supports_notnull_operator(&self) -> bool {
1150        false
1151    }
1152
1153    /// Returns true if this dialect allows an optional `SIGNED` suffix after integer data types.
1154    ///
1155    /// Example:
1156    /// ```sql
1157    /// CREATE TABLE t (i INT(20) SIGNED);
1158    /// ```
1159    ///
1160    /// Note that this is canonicalized to `INT(20)`.
1161    fn supports_data_type_signed_suffix(&self) -> bool {
1162        false
1163    }
1164
1165    /// Returns true if the dialect supports the `INTERVAL` data type with [Postgres]-style options.
1166    ///
1167    /// Examples:
1168    /// ```sql
1169    /// CREATE TABLE t (i INTERVAL YEAR TO MONTH);
1170    /// SELECT '1 second'::INTERVAL HOUR TO SECOND(3);
1171    /// ```
1172    ///
1173    /// See [`crate::ast::DataType::Interval`] and [`crate::ast::IntervalFields`].
1174    ///
1175    /// [Postgres]: https://www.postgresql.org/docs/17/datatype-datetime.html
1176    fn supports_interval_options(&self) -> bool {
1177        false
1178    }
1179
1180    /// Returns true if the dialect supports specifying which table to copy
1181    /// the schema from inside parenthesis.
1182    ///
1183    /// Not parenthesized:
1184    /// '''sql
1185    /// CREATE TABLE new LIKE old ...
1186    /// '''
1187    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
1188    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
1189    ///
1190    /// Parenthesized:
1191    /// '''sql
1192    /// CREATE TABLE new (LIKE old ...)
1193    /// '''
1194    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
1195    fn supports_create_table_like_parenthesized(&self) -> bool {
1196        false
1197    }
1198
1199    /// Returns true if the dialect supports `SEMANTIC_VIEW()` table functions.
1200    ///
1201    /// ```sql
1202    /// SELECT * FROM SEMANTIC_VIEW(
1203    ///     model_name
1204    ///     DIMENSIONS customer.name, customer.region
1205    ///     METRICS orders.revenue, orders.count
1206    ///     WHERE customer.active = true
1207    /// )
1208    /// ```
1209    fn supports_semantic_view_table_factor(&self) -> bool {
1210        false
1211    }
1212}
1213
1214/// This represents the operators for which precedence must be defined
1215///
1216/// higher number -> higher precedence
1217#[derive(Debug, Clone, Copy)]
1218pub enum Precedence {
1219    Period,
1220    DoubleColon,
1221    AtTz,
1222    MulDivModOp,
1223    PlusMinus,
1224    Xor,
1225    Ampersand,
1226    Caret,
1227    Pipe,
1228    Between,
1229    Eq,
1230    Like,
1231    Is,
1232    PgOther,
1233    UnaryNot,
1234    And,
1235    Or,
1236}
1237
1238impl dyn Dialect {
1239    #[inline]
1240    pub fn is<T: Dialect>(&self) -> bool {
1241        // borrowed from `Any` implementation
1242        TypeId::of::<T>() == self.dialect()
1243    }
1244}
1245
1246/// Returns the built in [`Dialect`] corresponding to `dialect_name`.
1247///
1248/// See [`Dialect`] documentation for an example.
1249pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect>> {
1250    let dialect_name = dialect_name.as_ref();
1251    match dialect_name.to_lowercase().as_str() {
1252        "generic" => Some(Box::new(GenericDialect)),
1253        "mysql" => Some(Box::new(MySqlDialect {})),
1254        "postgresql" | "postgres" => Some(Box::new(PostgreSqlDialect {})),
1255        "hive" => Some(Box::new(HiveDialect {})),
1256        "sqlite" => Some(Box::new(SQLiteDialect {})),
1257        "snowflake" => Some(Box::new(SnowflakeDialect)),
1258        "redshift" => Some(Box::new(RedshiftSqlDialect {})),
1259        "mssql" => Some(Box::new(MsSqlDialect {})),
1260        "clickhouse" => Some(Box::new(ClickHouseDialect {})),
1261        "bigquery" => Some(Box::new(BigQueryDialect)),
1262        "ansi" => Some(Box::new(AnsiDialect {})),
1263        "duckdb" => Some(Box::new(DuckDbDialect {})),
1264        "databricks" => Some(Box::new(DatabricksDialect {})),
1265        "oracle" => Some(Box::new(OracleDialect {})),
1266        _ => None,
1267    }
1268}
1269
1270#[cfg(test)]
1271mod tests {
1272    use super::*;
1273
1274    struct DialectHolder<'a> {
1275        dialect: &'a dyn Dialect,
1276    }
1277
1278    #[test]
1279    fn test_is_dialect() {
1280        let generic_dialect: &dyn Dialect = &GenericDialect {};
1281        let ansi_dialect: &dyn Dialect = &AnsiDialect {};
1282
1283        let generic_holder = DialectHolder {
1284            dialect: generic_dialect,
1285        };
1286        let ansi_holder = DialectHolder {
1287            dialect: ansi_dialect,
1288        };
1289
1290        assert!(dialect_of!(generic_holder is GenericDialect |  AnsiDialect),);
1291        assert!(!dialect_of!(generic_holder is  AnsiDialect));
1292        assert!(dialect_of!(ansi_holder is AnsiDialect));
1293        assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
1294        assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
1295    }
1296
1297    #[test]
1298    fn test_dialect_from_str() {
1299        assert!(parse_dialect("generic").is::<GenericDialect>());
1300        assert!(parse_dialect("mysql").is::<MySqlDialect>());
1301        assert!(parse_dialect("MySql").is::<MySqlDialect>());
1302        assert!(parse_dialect("postgresql").is::<PostgreSqlDialect>());
1303        assert!(parse_dialect("postgres").is::<PostgreSqlDialect>());
1304        assert!(parse_dialect("hive").is::<HiveDialect>());
1305        assert!(parse_dialect("sqlite").is::<SQLiteDialect>());
1306        assert!(parse_dialect("snowflake").is::<SnowflakeDialect>());
1307        assert!(parse_dialect("SnowFlake").is::<SnowflakeDialect>());
1308        assert!(parse_dialect("MsSql").is::<MsSqlDialect>());
1309        assert!(parse_dialect("clickhouse").is::<ClickHouseDialect>());
1310        assert!(parse_dialect("ClickHouse").is::<ClickHouseDialect>());
1311        assert!(parse_dialect("bigquery").is::<BigQueryDialect>());
1312        assert!(parse_dialect("BigQuery").is::<BigQueryDialect>());
1313        assert!(parse_dialect("ansi").is::<AnsiDialect>());
1314        assert!(parse_dialect("ANSI").is::<AnsiDialect>());
1315        assert!(parse_dialect("duckdb").is::<DuckDbDialect>());
1316        assert!(parse_dialect("DuckDb").is::<DuckDbDialect>());
1317        assert!(parse_dialect("DataBricks").is::<DatabricksDialect>());
1318        assert!(parse_dialect("databricks").is::<DatabricksDialect>());
1319
1320        // error cases
1321        assert!(dialect_from_str("Unknown").is_none());
1322        assert!(dialect_from_str("").is_none());
1323    }
1324
1325    fn parse_dialect(v: &str) -> Box<dyn Dialect> {
1326        dialect_from_str(v).unwrap()
1327    }
1328
1329    #[test]
1330    fn identifier_quote_style() {
1331        let tests: Vec<(&dyn Dialect, &str, Option<char>)> = vec![
1332            (&GenericDialect {}, "id", None),
1333            (&SQLiteDialect {}, "id", Some('`')),
1334            (&PostgreSqlDialect {}, "id", Some('"')),
1335        ];
1336
1337        for (dialect, ident, expected) in tests {
1338            let actual = dialect.identifier_quote_style(ident);
1339
1340            assert_eq!(actual, expected);
1341        }
1342    }
1343
1344    #[test]
1345    fn parse_with_wrapped_dialect() {
1346        /// Wrapper for a dialect. In a real-world example, this wrapper
1347        /// would tweak the behavior of the dialect. For the test case,
1348        /// it wraps all methods unaltered.
1349        #[derive(Debug)]
1350        struct WrappedDialect(MySqlDialect);
1351
1352        impl Dialect for WrappedDialect {
1353            fn dialect(&self) -> std::any::TypeId {
1354                self.0.dialect()
1355            }
1356
1357            fn is_identifier_start(&self, ch: char) -> bool {
1358                self.0.is_identifier_start(ch)
1359            }
1360
1361            fn is_delimited_identifier_start(&self, ch: char) -> bool {
1362                self.0.is_delimited_identifier_start(ch)
1363            }
1364
1365            fn is_nested_delimited_identifier_start(&self, ch: char) -> bool {
1366                self.0.is_nested_delimited_identifier_start(ch)
1367            }
1368
1369            fn peek_nested_delimited_identifier_quotes(
1370                &self,
1371                chars: std::iter::Peekable<std::str::Chars<'_>>,
1372            ) -> Option<(char, Option<char>)> {
1373                self.0.peek_nested_delimited_identifier_quotes(chars)
1374            }
1375
1376            fn identifier_quote_style(&self, identifier: &str) -> Option<char> {
1377                self.0.identifier_quote_style(identifier)
1378            }
1379
1380            fn supports_string_literal_backslash_escape(&self) -> bool {
1381                self.0.supports_string_literal_backslash_escape()
1382            }
1383
1384            fn supports_filter_during_aggregation(&self) -> bool {
1385                self.0.supports_filter_during_aggregation()
1386            }
1387
1388            fn supports_within_after_array_aggregation(&self) -> bool {
1389                self.0.supports_within_after_array_aggregation()
1390            }
1391
1392            fn supports_group_by_expr(&self) -> bool {
1393                self.0.supports_group_by_expr()
1394            }
1395
1396            fn supports_in_empty_list(&self) -> bool {
1397                self.0.supports_in_empty_list()
1398            }
1399
1400            fn convert_type_before_value(&self) -> bool {
1401                self.0.convert_type_before_value()
1402            }
1403
1404            fn parse_prefix(
1405                &self,
1406                parser: &mut sqlparser::parser::Parser,
1407            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
1408                self.0.parse_prefix(parser)
1409            }
1410
1411            fn parse_infix(
1412                &self,
1413                parser: &mut sqlparser::parser::Parser,
1414                expr: &Expr,
1415                precedence: u8,
1416            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
1417                self.0.parse_infix(parser, expr, precedence)
1418            }
1419
1420            fn get_next_precedence(
1421                &self,
1422                parser: &sqlparser::parser::Parser,
1423            ) -> Option<Result<u8, sqlparser::parser::ParserError>> {
1424                self.0.get_next_precedence(parser)
1425            }
1426
1427            fn parse_statement(
1428                &self,
1429                parser: &mut sqlparser::parser::Parser,
1430            ) -> Option<Result<Statement, sqlparser::parser::ParserError>> {
1431                self.0.parse_statement(parser)
1432            }
1433
1434            fn is_identifier_part(&self, ch: char) -> bool {
1435                self.0.is_identifier_part(ch)
1436            }
1437        }
1438
1439        #[allow(clippy::needless_raw_string_hashes)]
1440        let statement = r#"SELECT 'Wayne\'s World'"#;
1441        let res1 = Parser::parse_sql(&MySqlDialect {}, statement);
1442        let res2 = Parser::parse_sql(&WrappedDialect(MySqlDialect {}), statement);
1443        assert!(res1.is_ok());
1444        assert_eq!(res1, res2);
1445    }
1446}