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