Skip to main content

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 spark;
32mod sqlite;
33mod teradata;
34
35use core::any::{Any, TypeId};
36use core::fmt::Debug;
37use core::iter::Peekable;
38use core::str::Chars;
39
40use log::debug;
41
42pub use self::ansi::AnsiDialect;
43pub use self::bigquery::BigQueryDialect;
44pub use self::clickhouse::ClickHouseDialect;
45pub use self::databricks::DatabricksDialect;
46pub use self::duckdb::DuckDbDialect;
47pub use self::generic::GenericDialect;
48pub use self::hive::HiveDialect;
49pub use self::mssql::MsSqlDialect;
50pub use self::mysql::MySqlDialect;
51pub use self::oracle::OracleDialect;
52pub use self::postgresql::PostgreSqlDialect;
53pub use self::redshift::RedshiftSqlDialect;
54pub use self::snowflake::parse_snowflake_stage_name;
55pub use self::snowflake::SnowflakeDialect;
56pub use self::spark::SparkSqlDialect;
57pub use self::sqlite::SQLiteDialect;
58pub use self::teradata::TeradataDialect;
59
60/// Macro for streamlining the creation of derived `Dialect` objects.
61/// The generated struct includes `new()` and `default()` constructors.
62/// Requires the `derive-dialect` feature.
63///
64/// # Syntax
65///
66/// ```text
67/// derive_dialect!(NewDialect, BaseDialect);
68/// derive_dialect!(NewDialect, BaseDialect, overrides = { method = value, ... });
69/// derive_dialect!(NewDialect, BaseDialect, preserve_type_id = true);
70/// derive_dialect!(NewDialect, BaseDialect, preserve_type_id = true, overrides = { ... });
71/// ```
72///
73/// # Example
74///
75/// ```
76/// use sqlparser::derive_dialect;
77/// use sqlparser::dialect::{Dialect, GenericDialect};
78///
79/// // Override boolean methods (supports_*, allow_*, etc.)
80/// derive_dialect!(CustomDialect, GenericDialect, overrides = {
81///     supports_order_by_all = true,
82///     supports_nested_comments = true,
83/// });
84///
85/// let dialect = CustomDialect::new();
86/// assert!(dialect.supports_order_by_all());
87/// assert!(dialect.supports_nested_comments());
88/// ```
89///
90/// # Overriding `identifier_quote_style`
91///
92/// Use a char literal or `None`:
93/// ```
94/// use sqlparser::derive_dialect;
95/// use sqlparser::dialect::{Dialect, PostgreSqlDialect};
96///
97/// derive_dialect!(BacktickPostgreSqlDialect, PostgreSqlDialect,
98///     preserve_type_id = true,
99///     overrides = { identifier_quote_style = '`' }
100/// );
101/// let d: &dyn Dialect = &BacktickPostgreSqlDialect::new();
102/// assert_eq!(d.identifier_quote_style("foo"), Some('`'));
103///
104/// derive_dialect!(QuotelessPostgreSqlDialect, PostgreSqlDialect,
105///     preserve_type_id = true,
106///     overrides = { identifier_quote_style = None }
107/// );
108/// let d: &dyn Dialect = &QuotelessPostgreSqlDialect::new();
109/// assert_eq!(d.identifier_quote_style("foo"), None);
110/// ```
111///
112/// # Type Identity
113///
114/// By default, derived dialects have their own `TypeId`. Set `preserve_type_id = true` to
115/// retain the base dialect's identity with respect to the parser's `dialect.is::<T>()` checks:
116/// ```
117/// use sqlparser::derive_dialect;
118/// use sqlparser::dialect::{Dialect, GenericDialect};
119///
120/// derive_dialect!(EnhancedGenericDialect, GenericDialect,
121///     preserve_type_id = true,
122///     overrides = {
123///         supports_order_by_all = true,
124///         supports_nested_comments = true,
125///     }
126/// );
127/// let d: &dyn Dialect = &EnhancedGenericDialect::new();
128/// assert!(d.is::<GenericDialect>());  // still recognized as a GenericDialect
129/// assert!(d.supports_nested_comments());
130/// assert!(d.supports_order_by_all());
131/// ```
132#[cfg(feature = "derive-dialect")]
133pub use sqlparser_derive::derive_dialect;
134
135use crate::ast::{ColumnOption, Expr, GranteesType, Ident, ObjectNamePart, Statement};
136pub use crate::keywords;
137use crate::keywords::Keyword;
138use crate::parser::{Parser, ParserError};
139use crate::tokenizer::Token;
140
141#[cfg(not(feature = "std"))]
142use alloc::boxed::Box;
143
144/// Convenience check if a [`Parser`] uses a certain dialect.
145///
146/// Note: when possible, please use the new style, adding a method to
147/// the [`Dialect`] trait rather than using this macro.
148///
149/// The benefits of adding a method on `Dialect` over this macro are:
150/// 1. user defined [`Dialect`]s can customize the parsing behavior
151/// 2. The differences between dialects can be clearly documented in the trait
152///
153/// `dialect_of!(parser is SQLiteDialect | GenericDialect)` evaluates
154/// to `true` if `parser.dialect` is one of the [`Dialect`]s specified.
155macro_rules! dialect_of {
156    ( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
157        ($($parsed_dialect.dialect.is::<$dialect_type>())||+)
158    };
159}
160
161// Similar to above, but for applying directly against an instance of dialect
162// instead of a struct member named dialect. This avoids lifetime issues when
163// mixing match guards and token references.
164macro_rules! dialect_is {
165    ($dialect:ident is $($dialect_type:ty)|+) => {
166        ($($dialect.is::<$dialect_type>())||+)
167    }
168}
169
170/// Encapsulates the differences between SQL implementations.
171///
172/// # SQL Dialects
173///
174/// SQL implementations deviate from one another, either due to
175/// custom extensions or various historical reasons. This trait
176/// encapsulates the parsing differences between dialects.
177///
178/// [`GenericDialect`] is the most permissive dialect, and parses the union of
179/// all the other dialects, when there is no ambiguity. However, it does not
180/// currently allow `CREATE TABLE` statements without types specified for all
181/// columns; use [`SQLiteDialect`] if you require that.
182///
183/// # Examples
184/// Most users create a [`Dialect`] directly, as shown on the [module
185/// level documentation]:
186///
187/// ```
188/// # use sqlparser::dialect::AnsiDialect;
189/// let dialect = AnsiDialect {};
190/// ```
191///
192/// It is also possible to dynamically create a [`Dialect`] from its
193/// name. For example:
194///
195/// ```
196/// # use sqlparser::dialect::{AnsiDialect, dialect_from_str};
197/// let dialect = dialect_from_str("ansi").unwrap();
198///
199/// // Parsed dialect is an instance of `AnsiDialect`:
200/// assert!(dialect.is::<AnsiDialect>());
201/// ```
202///
203/// [module level documentation]: crate
204pub trait Dialect: Debug + Any {
205    /// Determine the [`TypeId`] of this dialect.
206    ///
207    /// By default, return the same [`TypeId`] as [`Any::type_id`]. Can be overridden by
208    /// dialects that behave like other dialects (for example, when wrapping a dialect).
209    fn dialect(&self) -> TypeId {
210        self.type_id()
211    }
212
213    /// Determine if a character starts a quoted identifier. The default
214    /// implementation, accepting "double quoted" ids is both ANSI-compliant
215    /// and appropriate for most dialects (with the notable exception of
216    /// MySQL, MS SQL, and sqlite). You can accept one of characters listed
217    /// in `Word::matching_end_quote` here
218    fn is_delimited_identifier_start(&self, ch: char) -> bool {
219        ch == '"' || ch == '`'
220    }
221
222    /// Determine if a character starts a potential nested quoted identifier.
223    /// Example: RedShift supports the following quote styles to all mean the same thing:
224    /// ```sql
225    /// SELECT 1 AS foo;
226    /// SELECT 1 AS "foo";
227    /// SELECT 1 AS [foo];
228    /// SELECT 1 AS ["foo"];
229    /// ```
230    fn is_nested_delimited_identifier_start(&self, _ch: char) -> bool {
231        false
232    }
233
234    /// Only applicable whenever [`Self::is_nested_delimited_identifier_start`] returns true
235    /// If the next sequence of tokens potentially represent a nested identifier, then this method
236    /// returns a tuple containing the outer quote style, and if present, the inner (nested) quote style.
237    ///
238    /// Example (Redshift):
239    /// ```text
240    /// `["foo"]` => Some(`[`, Some(`"`))
241    /// `[foo]` => Some(`[`, None)
242    /// `[0]` => None
243    /// `"foo"` => None
244    /// ```
245    fn peek_nested_delimited_identifier_quotes(
246        &self,
247        mut _chars: Peekable<Chars<'_>>,
248    ) -> Option<(char, Option<char>)> {
249        None
250    }
251
252    /// Return the character used to quote identifiers.
253    fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
254        None
255    }
256
257    /// Determine if a character is a valid start character for an unquoted identifier
258    fn is_identifier_start(&self, ch: char) -> bool;
259
260    /// Determine if a character is a valid unquoted identifier character
261    fn is_identifier_part(&self, ch: char) -> bool;
262
263    /// Most dialects do not have custom operators. Override this method to provide custom operators.
264    fn is_custom_operator_part(&self, _ch: char) -> bool {
265        false
266    }
267
268    /// Determine if the dialect supports escaping characters via '\' in string literals.
269    ///
270    /// Some dialects like BigQuery and Snowflake support this while others like
271    /// Postgres do not. Such that the following is accepted by the former but
272    /// rejected by the latter.
273    /// ```sql
274    /// SELECT 'ab\'cd';
275    /// ```
276    ///
277    /// Conversely, such dialects reject the following statement which
278    /// otherwise would be valid in the other dialects.
279    /// ```sql
280    /// SELECT '\';
281    /// ```
282    fn supports_string_literal_backslash_escape(&self) -> bool {
283        false
284    }
285
286    /// Determine whether the dialect strips the backslash when escaping LIKE wildcards (%, _).
287    ///
288    /// [MySQL] has a special case when escaping single quoted strings which leaves these unescaped
289    /// so they can be used in LIKE patterns without double-escaping (as is necessary in other
290    /// escaping dialects, such as [Snowflake]). Generally, special characters have escaping rules
291    /// causing them to be replaced with a different byte sequences (e.g. `'\0'` becoming the zero
292    /// byte), and the default if an escaped character does not have a specific escaping rule is to
293    /// strip the backslash (e.g. there is no rule for `h`, so `'\h' = 'h'`). MySQL's special case
294    /// for ignoring LIKE wildcard escapes is to *not* strip the backslash, so that `'\%' = '\\%'`.
295    /// This applies to all string literals though, not just those used in LIKE patterns.
296    ///
297    /// ```text
298    /// mysql> select '\_', hex('\\'), hex('_'), hex('\_');
299    /// +----+-----------+----------+-----------+
300    /// | \_ | hex('\\') | hex('_') | hex('\_') |
301    /// +----+-----------+----------+-----------+
302    /// | \_ | 5C        | 5F       | 5C5F      |
303    /// +----+-----------+----------+-----------+
304    /// 1 row in set (0.00 sec)
305    /// ```
306    ///
307    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/string-literals.html
308    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/functions/like#usage-notes
309    fn ignores_wildcard_escapes(&self) -> bool {
310        false
311    }
312
313    /// Determine if the dialect supports string literals with `U&` prefix.
314    /// This is used to specify Unicode code points in string literals.
315    /// For example, in PostgreSQL, the following is a valid string literal:
316    /// ```sql
317    /// SELECT U&'\0061\0062\0063';
318    /// ```
319    /// This is equivalent to the string literal `'abc'`.
320    /// See
321    ///  - [Postgres docs](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE)
322    ///  - [H2 docs](http://www.h2database.com/html/grammar.html#string)
323    fn supports_unicode_string_literal(&self) -> bool {
324        false
325    }
326
327    /// Does the dialect support `FILTER (WHERE expr)` for aggregate queries?
328    fn supports_filter_during_aggregation(&self) -> bool {
329        false
330    }
331
332    /// Returns true if the dialect supports referencing another named window
333    /// within a window clause declaration.
334    ///
335    /// Example
336    /// ```sql
337    /// SELECT * FROM mytable
338    /// WINDOW mynamed_window AS another_named_window
339    /// ```
340    fn supports_window_clause_named_window_reference(&self) -> bool {
341        false
342    }
343
344    /// Returns true if the dialect supports `ARRAY_AGG() [WITHIN GROUP (ORDER BY)]` expressions.
345    /// Otherwise, the dialect should expect an `ORDER BY` without the `WITHIN GROUP` clause, e.g. [`ANSI`]
346    ///
347    /// [`ANSI`]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#array-aggregate-function
348    fn supports_within_after_array_aggregation(&self) -> bool {
349        false
350    }
351
352    /// Returns true if the dialect supports `PARTITION BY` appearing after `ORDER BY`
353    /// in a `CREATE TABLE` statement (in addition to the standard placement before `ORDER BY`).
354    ///
355    /// ClickHouse DDL uses this ordering:
356    /// <https://clickhouse.com/docs/en/sql-reference/statements/create/table#partition-by>
357    fn supports_partition_by_after_order_by(&self) -> bool {
358        false
359    }
360
361    /// Returns true if the dialect supports ClickHouse-style `ARRAY JOIN` / `LEFT ARRAY JOIN` /
362    /// `INNER ARRAY JOIN` syntax for unnesting arrays inline.
363    ///
364    /// <https://clickhouse.com/docs/en/sql-reference/statements/select/array-join>
365    fn supports_array_join_syntax(&self) -> bool {
366        false
367    }
368
369    /// Returns true if the dialects supports `group sets, roll up, or cube` expressions.
370    fn supports_group_by_expr(&self) -> bool {
371        false
372    }
373
374    /// Returns true if the dialects supports `GROUP BY` modifiers prefixed by a `WITH` keyword.
375    /// Example: `GROUP BY value WITH ROLLUP`.
376    fn supports_group_by_with_modifier(&self) -> bool {
377        false
378    }
379
380    /// Indicates whether the dialect supports left-associative join parsing
381    /// by default when parentheses are omitted in nested joins.
382    ///
383    /// Most dialects (like MySQL or Postgres) assume **left-associative** precedence,
384    /// so a query like:
385    ///
386    /// ```sql
387    /// SELECT * FROM t1 NATURAL JOIN t5 INNER JOIN t0 ON ...
388    /// ```
389    /// is interpreted as:
390    /// ```sql
391    /// ((t1 NATURAL JOIN t5) INNER JOIN t0 ON ...)
392    /// ```
393    /// and internally represented as a **flat list** of joins.
394    ///
395    /// In contrast, some dialects (e.g. **Snowflake**) assume **right-associative**
396    /// precedence and interpret the same query as:
397    /// ```sql
398    /// (t1 NATURAL JOIN (t5 INNER JOIN t0 ON ...))
399    /// ```
400    /// which results in a **nested join** structure in the AST.
401    ///
402    /// If this method returns `false`, the parser must build nested join trees
403    /// even in the absence of parentheses to reflect the correct associativity
404    fn supports_left_associative_joins_without_parens(&self) -> bool {
405        true
406    }
407
408    /// Returns true if the dialect supports the `(+)` syntax for OUTER JOIN.
409    fn supports_outer_join_operator(&self) -> bool {
410        false
411    }
412
413    /// Returns true if the dialect supports a join specification on CROSS JOIN.
414    fn supports_cross_join_constraint(&self) -> bool {
415        false
416    }
417
418    /// Returns true if the dialect supports CONNECT BY.
419    fn supports_connect_by(&self) -> bool {
420        false
421    }
422
423    /// Returns true if the dialect supports `EXECUTE IMMEDIATE` statements.
424    fn supports_execute_immediate(&self) -> bool {
425        false
426    }
427
428    /// Returns true if the dialect supports the MATCH_RECOGNIZE operation.
429    fn supports_match_recognize(&self) -> bool {
430        false
431    }
432
433    /// Returns true if the dialect supports `(NOT) IN ()` expressions
434    fn supports_in_empty_list(&self) -> bool {
435        false
436    }
437
438    /// Returns true if the dialect supports `BEGIN {DEFERRED | IMMEDIATE | EXCLUSIVE | TRY | CATCH} [TRANSACTION]` statements
439    fn supports_start_transaction_modifier(&self) -> bool {
440        false
441    }
442
443    /// Returns true if the dialect supports `END {TRY | CATCH}` statements
444    fn supports_end_transaction_modifier(&self) -> bool {
445        false
446    }
447
448    /// Returns true if the dialect supports named arguments of the form `FUN(a = '1', b = '2')`.
449    fn supports_named_fn_args_with_eq_operator(&self) -> bool {
450        false
451    }
452
453    /// Returns true if the dialect supports named arguments of the form `FUN(a : '1', b : '2')`.
454    fn supports_named_fn_args_with_colon_operator(&self) -> bool {
455        false
456    }
457
458    /// Returns true if the dialect supports named arguments of the form `FUN(a := '1', b := '2')`.
459    fn supports_named_fn_args_with_assignment_operator(&self) -> bool {
460        false
461    }
462
463    /// Returns true if the dialect supports named arguments of the form `FUN(a => '1', b => '2')`.
464    fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
465        true
466    }
467
468    /// Returns true if dialect supports argument name as arbitrary expression.
469    /// e.g. `FUN(LOWER('a'):'1',  b:'2')`
470    /// Such function arguments are represented in the AST by the `FunctionArg::ExprNamed` variant,
471    /// otherwise use the `FunctionArg::Named` variant (compatible reason).
472    fn supports_named_fn_args_with_expr_name(&self) -> bool {
473        false
474    }
475
476    /// Returns true if the dialect supports identifiers starting with a numeric
477    /// prefix such as tables named `59901_user_login`
478    fn supports_numeric_prefix(&self) -> bool {
479        false
480    }
481
482    /// Returns true if the dialect supports numbers containing underscores, e.g. `10_000_000`
483    fn supports_numeric_literal_underscores(&self) -> bool {
484        false
485    }
486
487    /// Returns true if the dialects supports specifying null treatment
488    /// as part of a window function's parameter list as opposed
489    /// to after the parameter list.
490    ///
491    /// i.e The following syntax returns true
492    /// ```sql
493    /// FIRST_VALUE(a IGNORE NULLS) OVER ()
494    /// ```
495    /// while the following syntax returns false
496    /// ```sql
497    /// FIRST_VALUE(a) IGNORE NULLS OVER ()
498    /// ```
499    fn supports_window_function_null_treatment_arg(&self) -> bool {
500        false
501    }
502
503    /// Returns true if the dialect supports defining structs or objects using a
504    /// syntax like `{'x': 1, 'y': 2, 'z': 3}`.
505    fn supports_dictionary_syntax(&self) -> bool {
506        false
507    }
508
509    /// Returns true if the dialect supports defining object using the
510    /// syntax like `Map {1: 10, 2: 20}`.
511    fn support_map_literal_syntax(&self) -> bool {
512        false
513    }
514
515    /// Returns true if the dialect supports lambda functions, for example:
516    ///
517    /// ```sql
518    /// SELECT transform(array(1, 2, 3), x -> x + 1); -- returns [2,3,4]
519    /// ```
520    fn supports_lambda_functions(&self) -> bool {
521        false
522    }
523
524    /// Returns true if the dialect supports multiple variable assignment
525    /// using parentheses in a `SET` variable declaration.
526    ///
527    /// ```sql
528    /// SET (variable[, ...]) = (expression[, ...]);
529    /// ```
530    fn supports_parenthesized_set_variables(&self) -> bool {
531        false
532    }
533
534    /// Returns true if the dialect supports multiple `SET` statements
535    /// in a single statement.
536    ///
537    /// ```sql
538    /// SET variable = expression [, variable = expression];
539    /// ```
540    fn supports_comma_separated_set_assignments(&self) -> bool {
541        false
542    }
543
544    /// Returns true if the dialect supports `ORDER BY` in `UPDATE` statements.
545    ///
546    /// ```sql
547    /// UPDATE foo SET bar = false WHERE foo = true ORDER BY foo ASC;
548    /// ```
549    /// See <https://dev.mysql.com/doc/refman/8.4/en/update.html>
550    fn supports_update_order_by(&self) -> bool {
551        false
552    }
553
554    /// Returns true if the dialect supports an `EXCEPT` clause following a
555    /// wildcard in a select list.
556    ///
557    /// For example
558    /// ```sql
559    /// SELECT * EXCEPT order_id FROM orders;
560    /// ```
561    fn supports_select_wildcard_except(&self) -> bool {
562        false
563    }
564
565    /// Returns true if the dialect has a CONVERT function which accepts a type first
566    /// and an expression second, e.g. `CONVERT(varchar, 1)`
567    fn convert_type_before_value(&self) -> bool {
568        false
569    }
570
571    /// Returns true if the dialect supports triple quoted string
572    /// e.g. `"""abc"""`
573    fn supports_triple_quoted_string(&self) -> bool {
574        false
575    }
576
577    /// Dialect-specific prefix parser override
578    fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
579        // return None to fall back to the default behavior
580        None
581    }
582
583    /// Does the dialect support trailing commas around the query?
584    fn supports_trailing_commas(&self) -> bool {
585        false
586    }
587
588    /// Does the dialect support parsing `LIMIT 1, 2` as `LIMIT 2 OFFSET 1`?
589    fn supports_limit_comma(&self) -> bool {
590        false
591    }
592
593    /// Returns true if the dialect supports concatenating of string literal
594    /// Example: `SELECT 'Hello ' "world" => SELECT 'Hello world'`
595    fn supports_string_literal_concatenation(&self) -> bool {
596        false
597    }
598
599    /// Returns true if the dialect supports concatenating string literals with a newline.
600    /// For example, the following statement would return `true`:
601    /// ```sql
602    /// SELECT 'abc' in (
603    ///   'a'
604    ///   'b'
605    ///   'c'
606    /// );
607    /// ```
608    fn supports_string_literal_concatenation_with_newline(&self) -> bool {
609        false
610    }
611
612    /// Does the dialect support trailing commas in the projection list?
613    fn supports_projection_trailing_commas(&self) -> bool {
614        self.supports_trailing_commas()
615    }
616
617    /// Returns true if the dialect supports trailing commas in the `FROM` clause of a `SELECT` statement.
618    /// Example: `SELECT 1 FROM T, U, LIMIT 1`
619    fn supports_from_trailing_commas(&self) -> bool {
620        false
621    }
622
623    /// Returns true if the dialect supports trailing commas in the
624    /// column definitions list of a `CREATE` statement.
625    /// Example: `CREATE TABLE T (x INT, y TEXT,)`
626    fn supports_column_definition_trailing_commas(&self) -> bool {
627        false
628    }
629
630    /// Returns true if the dialect supports double dot notation for object names
631    ///
632    /// Example
633    /// ```sql
634    /// SELECT * FROM db_name..table_name
635    /// ```
636    fn supports_object_name_double_dot_notation(&self) -> bool {
637        false
638    }
639
640    /// Return true if the dialect supports the STRUCT literal
641    ///
642    /// Example
643    /// ```sql
644    /// SELECT STRUCT(1 as one, 'foo' as foo, false)
645    /// ```
646    fn supports_struct_literal(&self) -> bool {
647        false
648    }
649
650    /// Return true if the dialect supports empty projections in SELECT statements
651    ///
652    /// Example
653    /// ```sql
654    /// SELECT from table_name
655    /// ```
656    fn supports_empty_projections(&self) -> bool {
657        false
658    }
659
660    /// Return true if the dialect supports wildcard expansion on
661    /// arbitrary expressions in projections.
662    ///
663    /// Example:
664    /// ```sql
665    /// SELECT STRUCT<STRING>('foo').* FROM T
666    /// ```
667    fn supports_select_expr_star(&self) -> bool {
668        false
669    }
670
671    /// Return true if the dialect supports "FROM-first" selects.
672    ///
673    /// Example:
674    /// ```sql
675    /// FROM table
676    /// SELECT *
677    /// ```
678    fn supports_from_first_select(&self) -> bool {
679        false
680    }
681
682    /// Return true if the dialect supports "FROM-first" inserts.
683    ///
684    /// Example:
685    /// ```sql
686    /// WITH cte AS (SELECT key FROM src)
687    /// FROM cte
688    /// INSERT OVERWRITE table my_table
689    /// SELECT *
690    ///
691    /// See <https://hive.apache.org/docs/latest/language/common-table-expression/>
692    /// ```
693    fn supports_from_first_insert(&self) -> bool {
694        false
695    }
696
697    /// Return true if the dialect supports pipe operator.
698    ///
699    /// Example:
700    /// ```sql
701    /// SELECT *
702    /// FROM table
703    /// |> limit 1
704    /// ```
705    ///
706    /// See <https://cloud.google.com/bigquery/docs/pipe-syntax-guide#basic_syntax>
707    fn supports_pipe_operator(&self) -> bool {
708        false
709    }
710
711    /// Does the dialect support MySQL-style `'user'@'host'` grantee syntax?
712    fn supports_user_host_grantee(&self) -> bool {
713        false
714    }
715
716    /// Does the dialect support the `MATCH() AGAINST()` syntax?
717    fn supports_match_against(&self) -> bool {
718        false
719    }
720
721    /// Returns true if the dialect supports an exclude option
722    /// following a wildcard in the projection section. For example:
723    /// `SELECT * EXCLUDE col1 FROM tbl`.
724    ///
725    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_EXCLUDE_list.html)
726    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select)
727    fn supports_select_wildcard_exclude(&self) -> bool {
728        false
729    }
730
731    /// Returns true if the dialect supports an exclude option
732    /// as the last item in the projection section, not necessarily
733    /// after a wildcard. For example:
734    /// `SELECT *, c1, c2 EXCLUDE c3 FROM tbl`
735    ///
736    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_EXCLUDE_list.html)
737    fn supports_select_exclude(&self) -> bool {
738        false
739    }
740
741    /// Returns true if the dialect supports specifying multiple options
742    /// in a `CREATE TABLE` statement for the structure of the new table. For example:
743    /// `CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a`
744    fn supports_create_table_multi_schema_info_sources(&self) -> bool {
745        false
746    }
747
748    /// Returns true if the dialect supports MySQL-specific SELECT modifiers
749    /// like `HIGH_PRIORITY`, `STRAIGHT_JOIN`, `SQL_SMALL_RESULT`, etc.
750    ///
751    /// For example:
752    /// ```sql
753    /// SELECT HIGH_PRIORITY STRAIGHT_JOIN SQL_SMALL_RESULT * FROM t1 JOIN t2 ON ...
754    /// ```
755    ///
756    /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/select.html)
757    fn supports_select_modifiers(&self) -> bool {
758        false
759    }
760
761    /// Dialect-specific infix parser override
762    ///
763    /// This method is called to parse the next infix expression.
764    ///
765    /// If `None` is returned, falls back to the default behavior.
766    fn parse_infix(
767        &self,
768        _parser: &mut Parser,
769        _expr: &Expr,
770        _precedence: u8,
771    ) -> Option<Result<Expr, ParserError>> {
772        // return None to fall back to the default behavior
773        None
774    }
775
776    /// Dialect-specific precedence override
777    ///
778    /// This method is called to get the precedence of the next token.
779    ///
780    /// If `None` is returned, falls back to the default behavior.
781    fn get_next_precedence(&self, _parser: &Parser) -> Option<Result<u8, ParserError>> {
782        // return None to fall back to the default behavior
783        None
784    }
785
786    /// Get the precedence of the next token, looking at the full token stream.
787    ///
788    /// A higher number => higher precedence
789    ///
790    /// See [`Self::get_next_precedence`] to override the behavior for just the
791    /// next token.
792    ///
793    /// The default implementation is used for many dialects, but can be
794    /// overridden to provide dialect-specific behavior.
795    fn get_next_precedence_default(&self, parser: &Parser) -> Result<u8, ParserError> {
796        if let Some(precedence) = self.get_next_precedence(parser) {
797            return precedence;
798        }
799        macro_rules! p {
800            ($precedence:ident) => {
801                self.prec_value(Precedence::$precedence)
802            };
803        }
804
805        let token = parser.peek_token_ref();
806        debug!("get_next_precedence_full() {token:?}");
807        match &token.token {
808            Token::Word(w) if w.keyword == Keyword::OR => Ok(p!(Or)),
809            Token::Word(w) if w.keyword == Keyword::AND => Ok(p!(And)),
810            Token::Word(w) if w.keyword == Keyword::XOR => Ok(p!(Xor)),
811
812            Token::Word(w) if w.keyword == Keyword::AT => {
813                match (
814                    &parser.peek_nth_token_ref(1).token,
815                    &parser.peek_nth_token_ref(2).token,
816                ) {
817                    (Token::Word(w), Token::Word(w2))
818                        if w.keyword == Keyword::TIME && w2.keyword == Keyword::ZONE =>
819                    {
820                        Ok(p!(AtTz))
821                    }
822                    _ => Ok(self.prec_unknown()),
823                }
824            }
825
826            Token::Word(w) if w.keyword == Keyword::NOT => {
827                match &parser.peek_nth_token_ref(1).token {
828                    // The precedence of NOT varies depending on keyword that
829                    // follows it. If it is followed by IN, BETWEEN, or LIKE,
830                    // it takes on the precedence of those tokens. Otherwise, it
831                    // is not an infix operator, and therefore has zero
832                    // precedence.
833                    Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
834                    Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
835                    Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
836                    Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
837                    Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
838                    Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
839                    Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
840                    Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
841                    Token::Word(w) if w.keyword == Keyword::MEMBER => Ok(p!(Like)),
842                    Token::Word(w)
843                        if w.keyword == Keyword::NULL && !parser.in_column_definition_state() =>
844                    {
845                        Ok(p!(Is))
846                    }
847                    _ => Ok(self.prec_unknown()),
848                }
849            }
850            Token::Word(w) if w.keyword == Keyword::NOTNULL && self.supports_notnull_operator() => {
851                Ok(p!(Is))
852            }
853            Token::Word(w) if w.keyword == Keyword::IS => Ok(p!(Is)),
854            Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
855            Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
856            Token::Word(w) if w.keyword == Keyword::OVERLAPS => Ok(p!(Between)),
857            Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
858            Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
859            Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
860            Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
861            Token::Word(w) if w.keyword == Keyword::MATCH => Ok(p!(Like)),
862            Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
863            Token::Word(w) if w.keyword == Keyword::MEMBER => Ok(p!(Like)),
864            Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(p!(Between)),
865            Token::Word(w) if w.keyword == Keyword::DIV => Ok(p!(MulDivModOp)),
866            Token::Period => Ok(p!(Period)),
867            Token::Assignment
868            | Token::Eq
869            | Token::Lt
870            | Token::LtEq
871            | Token::Neq
872            | Token::Gt
873            | Token::GtEq
874            | Token::DoubleEq
875            | Token::Tilde
876            | Token::TildeAsterisk
877            | Token::ExclamationMarkTilde
878            | Token::ExclamationMarkTildeAsterisk
879            | Token::DoubleTilde
880            | Token::DoubleTildeAsterisk
881            | Token::ExclamationMarkDoubleTilde
882            | Token::ExclamationMarkDoubleTildeAsterisk
883            | Token::Spaceship => Ok(p!(Eq)),
884            Token::Pipe
885            | Token::QuestionMarkDash
886            | Token::DoubleSharp
887            | Token::Overlap
888            | Token::AmpersandLeftAngleBracket
889            | Token::AmpersandRightAngleBracket
890            | Token::QuestionMarkDashVerticalBar
891            | Token::AmpersandLeftAngleBracketVerticalBar
892            | Token::VerticalBarAmpersandRightAngleBracket
893            | Token::TwoWayArrow
894            | Token::LeftAngleBracketCaret
895            | Token::RightAngleBracketCaret
896            | Token::QuestionMarkSharp
897            | Token::QuestionMarkDoubleVerticalBar
898            | Token::QuestionPipe
899            | Token::TildeEqual
900            | Token::AtSign
901            | Token::ShiftLeftVerticalBar
902            | Token::VerticalBarShiftRight => Ok(p!(Pipe)),
903            Token::Caret | Token::Sharp | Token::ShiftRight | Token::ShiftLeft => Ok(p!(Caret)),
904            Token::Ampersand => Ok(p!(Ampersand)),
905            Token::Plus | Token::Minus => Ok(p!(PlusMinus)),
906            Token::Mul | Token::Div | Token::DuckIntDiv | Token::Mod | Token::StringConcat => {
907                Ok(p!(MulDivModOp))
908            }
909            Token::DoubleColon | Token::ExclamationMark | Token::LBracket | Token::CaretAt => {
910                Ok(p!(DoubleColon))
911            }
912            Token::Colon => match &parser.peek_nth_token_ref(1).token {
913                // When colon is followed by a string or a number, it's usually in MAP syntax.
914                Token::SingleQuotedString(_) | Token::Number(_, _) => Ok(self.prec_unknown()),
915                // In other cases, it's used in semi-structured data traversal like in variant or JSON
916                // string columns. See `JsonAccess`.
917                _ => Ok(p!(Colon)),
918            },
919            Token::Arrow
920            | Token::LongArrow
921            | Token::HashArrow
922            | Token::HashLongArrow
923            | Token::AtArrow
924            | Token::ArrowAt
925            | Token::HashMinus
926            | Token::AtQuestion
927            | Token::AtAt
928            | Token::Question
929            | Token::QuestionAnd
930            | Token::CustomBinaryOperator(_) => Ok(p!(PgOther)),
931            _ => Ok(self.prec_unknown()),
932        }
933    }
934
935    /// Dialect-specific statement parser override
936    ///
937    /// This method is called to parse the next statement.
938    ///
939    /// If `None` is returned, falls back to the default behavior.
940    fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
941        // return None to fall back to the default behavior
942        None
943    }
944
945    /// Dialect-specific column option parser override
946    ///
947    /// This method is called to parse the next column option.
948    ///
949    /// If `None` is returned, falls back to the default behavior.
950    fn parse_column_option(
951        &self,
952        _parser: &mut Parser,
953    ) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
954        // return None to fall back to the default behavior
955        Ok(None)
956    }
957
958    /// Decide the lexical Precedence of operators.
959    ///
960    /// Uses (APPROXIMATELY) <https://www.postgresql.org/docs/7.0/operators.htm#AEN2026> as a reference
961    fn prec_value(&self, prec: Precedence) -> u8 {
962        match prec {
963            Precedence::Period => 100,
964            Precedence::DoubleColon => 50,
965            Precedence::AtTz => 41,
966            Precedence::MulDivModOp => 40,
967            Precedence::PlusMinus => 30,
968            Precedence::Xor => 24,
969            Precedence::Ampersand => 23,
970            Precedence::Caret => 22,
971            Precedence::Pipe => 21,
972            Precedence::Colon => 21,
973            Precedence::Between => 20,
974            Precedence::Eq => 20,
975            Precedence::Like => 19,
976            Precedence::Is => 17,
977            Precedence::PgOther => 16,
978            Precedence::UnaryNot => 15,
979            Precedence::And => 10,
980            Precedence::Or => 5,
981        }
982    }
983
984    /// Returns the precedence when the precedence is otherwise unknown
985    fn prec_unknown(&self) -> u8 {
986        0
987    }
988
989    /// Returns true if this dialect requires the `TABLE` keyword after `DESCRIBE`
990    ///
991    /// Defaults to false.
992    ///
993    /// If true, the following statement is valid: `DESCRIBE TABLE my_table`
994    /// If false, the following statements are valid: `DESCRIBE my_table` and `DESCRIBE table`
995    fn describe_requires_table_keyword(&self) -> bool {
996        false
997    }
998
999    /// Returns true if this dialect allows the `EXTRACT` function to words other than [`Keyword`].
1000    fn allow_extract_custom(&self) -> bool {
1001        false
1002    }
1003
1004    /// Returns true if this dialect allows the `EXTRACT` function to use single quotes in the part being extracted.
1005    fn allow_extract_single_quotes(&self) -> bool {
1006        false
1007    }
1008
1009    /// Returns true if this dialect supports the `EXTRACT` function
1010    /// with a comma separator instead of `FROM`.
1011    ///
1012    /// Example:
1013    /// ```sql
1014    /// SELECT EXTRACT(YEAR, date_column) FROM table;
1015    /// ```
1016    ///
1017    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/extract)
1018    fn supports_extract_comma_syntax(&self) -> bool {
1019        false
1020    }
1021
1022    /// Returns true if this dialect supports a subquery passed to a function
1023    /// as the only argument without enclosing parentheses.
1024    ///
1025    /// Example:
1026    /// ```sql
1027    /// SELECT FLATTEN(SELECT * FROM tbl);
1028    /// ```
1029    ///
1030    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/flatten)
1031    fn supports_subquery_as_function_arg(&self) -> bool {
1032        false
1033    }
1034
1035    /// Returns true if this dialect supports the `COMMENT` clause in
1036    /// `CREATE VIEW` statements using the `COMMENT = 'comment'` syntax.
1037    ///
1038    /// Example:
1039    /// ```sql
1040    /// CREATE VIEW v COMMENT = 'my comment' AS SELECT 1;
1041    /// ```
1042    ///
1043    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-view#optional-parameters)
1044    fn supports_create_view_comment_syntax(&self) -> bool {
1045        false
1046    }
1047
1048    /// Returns true if this dialect supports the `ARRAY` type without
1049    /// specifying an element type.
1050    ///
1051    /// Example:
1052    /// ```sql
1053    /// CREATE TABLE t (a ARRAY);
1054    /// ```
1055    ///
1056    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/data-types-semistructured#array)
1057    fn supports_array_typedef_without_element_type(&self) -> bool {
1058        false
1059    }
1060
1061    /// Returns true if this dialect supports extra parentheses around
1062    /// lone table names or derived tables in the `FROM` clause.
1063    ///
1064    /// Example:
1065    /// ```sql
1066    /// SELECT * FROM (mytable);
1067    /// SELECT * FROM ((SELECT 1));
1068    /// SELECT * FROM (mytable) AS alias;
1069    /// ```
1070    ///
1071    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/from)
1072    fn supports_parens_around_table_factor(&self) -> bool {
1073        false
1074    }
1075
1076    /// Returns true if this dialect supports `VALUES` as a table factor
1077    /// without requiring parentheses around the entire clause.
1078    ///
1079    /// Example:
1080    /// ```sql
1081    /// SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2);
1082    /// ```
1083    ///
1084    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/values)
1085    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-qry-select-values.html)
1086    fn supports_values_as_table_factor(&self) -> bool {
1087        false
1088    }
1089
1090    /// Returns true if this dialect allows dollar placeholders
1091    /// e.g. `SELECT $var` (SQLite)
1092    fn supports_dollar_placeholder(&self) -> bool {
1093        false
1094    }
1095
1096    /// Returns true if this dialect supports `$` as a prefix for money literals
1097    /// e.g. `SELECT $123.45` (SQL Server)
1098    fn supports_dollar_as_money_prefix(&self) -> bool {
1099        false
1100    }
1101
1102    /// Does the dialect support with clause in create index statement?
1103    /// e.g. `CREATE INDEX idx ON t WITH (key = value, key2)`
1104    fn supports_create_index_with_clause(&self) -> bool {
1105        false
1106    }
1107
1108    /// Whether `INTERVAL` expressions require units (called "qualifiers" in the ANSI SQL spec) to be specified,
1109    /// e.g. `INTERVAL 1 DAY` vs `INTERVAL 1`.
1110    ///
1111    /// Expressions within intervals (e.g. `INTERVAL '1' + '1' DAY`) are only allowed when units are required.
1112    ///
1113    /// See <https://github.com/sqlparser-rs/sqlparser-rs/pull/1398> for more information.
1114    ///
1115    /// When `true`:
1116    /// * `INTERVAL '1' DAY` is VALID
1117    /// * `INTERVAL 1 + 1 DAY` is VALID
1118    /// * `INTERVAL '1' + '1' DAY` is VALID
1119    /// * `INTERVAL '1'` is INVALID
1120    ///
1121    /// When `false`:
1122    /// * `INTERVAL '1'` is VALID
1123    /// * `INTERVAL '1' DAY` is VALID — unit is not required, but still allowed
1124    /// * `INTERVAL 1 + 1 DAY` is INVALID
1125    fn require_interval_qualifier(&self) -> bool {
1126        false
1127    }
1128
1129    /// Returns true if the dialect supports `EXPLAIN` statements with utility options
1130    /// e.g. `EXPLAIN (ANALYZE TRUE, BUFFERS TRUE) SELECT * FROM tbl;`
1131    fn supports_explain_with_utility_options(&self) -> bool {
1132        false
1133    }
1134
1135    /// Returns true if the dialect supports `ASC` and `DESC` in column definitions
1136    /// e.g. `CREATE TABLE t (a INT ASC, b INT DESC);`
1137    fn supports_asc_desc_in_column_definition(&self) -> bool {
1138        false
1139    }
1140
1141    /// Returns true if the dialect supports `a!` expressions
1142    fn supports_factorial_operator(&self) -> bool {
1143        false
1144    }
1145
1146    /// Returns true if the dialect supports `<<` and `>>` shift operators.
1147    fn supports_bitwise_shift_operators(&self) -> bool {
1148        false
1149    }
1150
1151    /// Returns true if the dialect supports nested comments
1152    /// e.g. `/* /* nested */ */`
1153    fn supports_nested_comments(&self) -> bool {
1154        false
1155    }
1156
1157    /// Returns true if the dialect supports optimizer hints in multiline comments
1158    /// e.g. `/*!50110 KEY_BLOCK_SIZE = 1024*/`
1159    fn supports_multiline_comment_hints(&self) -> bool {
1160        false
1161    }
1162
1163    /// Returns true if this dialect supports treating the equals operator `=` within a `SelectItem`
1164    /// as an alias assignment operator, rather than a boolean expression.
1165    /// For example: the following statements are equivalent for such a dialect:
1166    /// ```sql
1167    ///  SELECT col_alias = col FROM tbl;
1168    ///  SELECT col_alias AS col FROM tbl;
1169    /// ```
1170    fn supports_eq_alias_assignment(&self) -> bool {
1171        false
1172    }
1173
1174    /// Returns true if this dialect supports the `TRY_CONVERT` function
1175    fn supports_try_convert(&self) -> bool {
1176        false
1177    }
1178
1179    /// Returns true if the dialect supports `!a` syntax for boolean `NOT` expressions.
1180    fn supports_bang_not_operator(&self) -> bool {
1181        false
1182    }
1183
1184    /// Returns true if the dialect supports the `LISTEN`, `UNLISTEN` and `NOTIFY` statements
1185    fn supports_listen_notify(&self) -> bool {
1186        false
1187    }
1188
1189    /// Returns true if the dialect supports the `LOAD DATA` statement
1190    fn supports_load_data(&self) -> bool {
1191        false
1192    }
1193
1194    /// Returns true if the dialect supports the `LOAD extension` statement
1195    fn supports_load_extension(&self) -> bool {
1196        false
1197    }
1198
1199    /// Returns true if this dialect expects the `TOP` option
1200    /// before the `ALL`/`DISTINCT` options in a `SELECT` statement.
1201    fn supports_top_before_distinct(&self) -> bool {
1202        false
1203    }
1204
1205    /// Returns true if the dialect supports boolean literals (`true` and `false`).
1206    /// For example, in MSSQL these are treated as identifiers rather than boolean literals.
1207    fn supports_boolean_literals(&self) -> bool {
1208        true
1209    }
1210
1211    /// Returns true if this dialect supports the `LIKE 'pattern'` option in
1212    /// a `SHOW` statement before the `IN` option
1213    fn supports_show_like_before_in(&self) -> bool {
1214        false
1215    }
1216
1217    /// Returns true if this dialect supports the `COMMENT` statement
1218    fn supports_comment_on(&self) -> bool {
1219        false
1220    }
1221
1222    /// Returns true if the dialect supports the `CREATE TABLE SELECT` statement
1223    fn supports_create_table_select(&self) -> bool {
1224        false
1225    }
1226
1227    /// Returns true if the dialect accepts a comma-separated list of table-level
1228    /// options placed between the table name and the column-list parenthesis, e.g.
1229    ///
1230    /// ```sql
1231    /// CREATE TABLE foo, NO FALLBACK, NO BEFORE JOURNAL (col INTEGER)
1232    /// ```
1233    fn supports_leading_comma_before_table_options(&self) -> bool {
1234        false
1235    }
1236
1237    /// Returns true if the dialect supports PartiQL for querying semi-structured data
1238    /// <https://partiql.org/index.html>
1239    fn supports_partiql(&self) -> bool {
1240        false
1241    }
1242
1243    /// Returns true if the dialect supports the `CONSTRAINT` keyword without a name
1244    /// in table constraint definitions.
1245    ///
1246    /// Example:
1247    /// ```sql
1248    /// CREATE TABLE t (a INT, CONSTRAINT CHECK (a > 0))
1249    /// ```
1250    ///
1251    /// This is a MySQL extension; the SQL standard requires a name after `CONSTRAINT`.
1252    /// When the name is omitted, the output normalizes to just the constraint type
1253    /// without the `CONSTRAINT` keyword (e.g., `CHECK (a > 0)`).
1254    ///
1255    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1256    fn supports_constraint_keyword_without_name(&self) -> bool {
1257        false
1258    }
1259
1260    /// Returns true if the dialect supports the `KEY` keyword as part of
1261    /// column-level constraints in a `CREATE TABLE` statement.
1262    ///
1263    /// When enabled, the parser accepts these MySQL-specific column options:
1264    /// - `UNIQUE [KEY]` — optional `KEY` after `UNIQUE`
1265    /// - `[PRIMARY] KEY` — standalone `KEY` as shorthand for `PRIMARY KEY`
1266    ///
1267    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1268    fn supports_key_column_option(&self) -> bool {
1269        false
1270    }
1271
1272    /// Returns true if the specified keyword is reserved and cannot be
1273    /// used as an identifier without special handling like quoting.
1274    fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
1275        keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
1276    }
1277
1278    /// Returns reserved keywords that may prefix a select item expression
1279    /// e.g. `SELECT CONNECT_BY_ROOT name FROM Tbl2` (Snowflake)
1280    fn get_reserved_keywords_for_select_item_operator(&self) -> &[Keyword] {
1281        &[]
1282    }
1283
1284    /// Returns grantee types that should be treated as identifiers
1285    fn get_reserved_grantees_types(&self) -> &[GranteesType] {
1286        &[]
1287    }
1288
1289    /// Returns true if this dialect supports the `TABLESAMPLE` option
1290    /// before the table alias option. For example:
1291    ///
1292    /// Table sample before alias: `SELECT * FROM tbl AS t TABLESAMPLE (10)`
1293    /// Table sample after alias: `SELECT * FROM tbl TABLESAMPLE (10) AS t`
1294    ///
1295    /// <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#_7_6_table_reference>
1296    fn supports_table_sample_before_alias(&self) -> bool {
1297        false
1298    }
1299
1300    /// Returns true if this dialect supports the `INSERT INTO ... SET col1 = 1, ...` syntax.
1301    ///
1302    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/insert.html>
1303    fn supports_insert_set(&self) -> bool {
1304        false
1305    }
1306
1307    /// Does the dialect support table function in insertion?
1308    fn supports_insert_table_function(&self) -> bool {
1309        false
1310    }
1311
1312    /// Does the dialect support table queries in insertion?
1313    ///
1314    /// e.g. `SELECT INTO (<query>) ...`
1315    fn supports_insert_table_query(&self) -> bool {
1316        false
1317    }
1318
1319    /// Does the dialect support insert formats, e.g. `INSERT INTO ... FORMAT <format>`
1320    fn supports_insert_format(&self) -> bool {
1321        false
1322    }
1323
1324    /// Returns true if this dialect supports `INSERT INTO t [[AS] alias] ...`.
1325    fn supports_insert_table_alias(&self) -> bool {
1326        false
1327    }
1328
1329    /// Returns true if this dialect supports `SET` statements without an explicit
1330    /// assignment operator such as `=`. For example: `SET SHOWPLAN_XML ON`.
1331    fn supports_set_stmt_without_operator(&self) -> bool {
1332        false
1333    }
1334
1335    /// Returns true if the specified keyword should be parsed as a column identifier.
1336    /// See [keywords::RESERVED_FOR_COLUMN_ALIAS]
1337    fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1338        !keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw)
1339    }
1340
1341    /// Returns true if the specified keyword should be parsed as a select item alias.
1342    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
1343    /// to enable looking ahead if needed.
1344    fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1345        explicit || self.is_column_alias(kw, parser)
1346    }
1347
1348    /// Returns true if the specified keyword should be parsed as a table factor identifier.
1349    /// See [keywords::RESERVED_FOR_TABLE_FACTOR]
1350    fn is_table_factor(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1351        !keywords::RESERVED_FOR_TABLE_FACTOR.contains(kw)
1352    }
1353
1354    /// Returns true if the specified keyword should be parsed as a table factor alias.
1355    /// See [keywords::RESERVED_FOR_TABLE_ALIAS]
1356    fn is_table_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1357        !keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
1358    }
1359
1360    /// Returns true if the specified keyword should be parsed as a table factor alias.
1361    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
1362    /// to enable looking ahead if needed.
1363    fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1364        explicit || self.is_table_alias(kw, parser)
1365    }
1366
1367    /// Returns true if this dialect supports querying historical table data
1368    /// by specifying which version of the data to query.
1369    fn supports_table_versioning(&self) -> bool {
1370        false
1371    }
1372
1373    /// Returns true if this dialect supports the E'...' syntax for string literals
1374    ///
1375    /// Postgres: <https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE>
1376    fn supports_string_escape_constant(&self) -> bool {
1377        false
1378    }
1379
1380    /// Returns true if the dialect supports the table hints in the `FROM` clause.
1381    fn supports_table_hints(&self) -> bool {
1382        false
1383    }
1384
1385    /// Returns true if this dialect requires a whitespace character after `--` to start a single line comment.
1386    ///
1387    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/ansi-diff-comments.html>
1388    /// e.g. UPDATE account SET balance=balance--1
1389    //       WHERE account_id=5752             ^^^ will be interpreted as two minus signs instead of a comment
1390    fn requires_single_line_comment_whitespace(&self) -> bool {
1391        false
1392    }
1393
1394    /// Returns true if the dialect supports array type definition with brackets with
1395    /// an optional size. For example:
1396    /// ```CREATE TABLE my_table (arr1 INT[], arr2 INT[3])```
1397    /// ```SELECT x::INT[]```
1398    fn supports_array_typedef_with_brackets(&self) -> bool {
1399        false
1400    }
1401    /// Returns true if the dialect supports geometric types.
1402    ///
1403    /// Postgres: <https://www.postgresql.org/docs/9.5/functions-geometry.html>
1404    /// e.g. @@ circle '((0,0),10)'
1405    fn supports_geometric_types(&self) -> bool {
1406        false
1407    }
1408
1409    /// Returns true if the dialect supports `ORDER BY ALL`.
1410    /// `ALL` which means all columns of the SELECT clause.
1411    ///
1412    /// For example: ```SELECT * FROM addresses ORDER BY ALL;```.
1413    fn supports_order_by_all(&self) -> bool {
1414        false
1415    }
1416
1417    /// Returns true if the dialect supports PostgreSQL-style ordering operators:
1418    /// `ORDER BY expr USING <operator>`.
1419    ///
1420    /// For example: `SELECT * FROM t ORDER BY a USING <`.
1421    fn supports_order_by_using_operator(&self) -> bool {
1422        false
1423    }
1424
1425    /// Returns true if the dialect supports `SET NAMES <charset_name> [COLLATE <collation_name>]`.
1426    ///
1427    /// - [MySQL](https://dev.mysql.com/doc/refman/8.4/en/set-names.html)
1428    /// - [PostgreSQL](https://www.postgresql.org/docs/17/sql-set.html)
1429    ///
1430    /// Note: Postgres doesn't support the `COLLATE` clause, but we permissively parse it anyway.
1431    fn supports_set_names(&self) -> bool {
1432        false
1433    }
1434
1435    /// Returns true if the dialect supports space-separated column options
1436    /// in a `CREATE TABLE` statement. For example:
1437    /// ```sql
1438    /// CREATE TABLE tbl (
1439    ///     col INT NOT NULL DEFAULT 0
1440    /// );
1441    /// ```
1442    fn supports_space_separated_column_options(&self) -> bool {
1443        false
1444    }
1445
1446    /// Returns true if the dialect supports the `USING` clause in an `ALTER COLUMN` statement.
1447    /// Example:
1448    ///  ```sql
1449    ///  ALTER TABLE tbl ALTER COLUMN col SET DATA TYPE <type> USING <exp>`
1450    /// ```
1451    fn supports_alter_column_type_using(&self) -> bool {
1452        false
1453    }
1454
1455    /// Returns true if the dialect supports `ALTER TABLE tbl DROP COLUMN c1, ..., cn`
1456    fn supports_comma_separated_drop_column_list(&self) -> bool {
1457        false
1458    }
1459
1460    /// Returns true if the dialect considers the specified ident as a function
1461    /// that returns an identifier. Typically used to generate identifiers
1462    /// programmatically.
1463    ///
1464    /// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
1465    fn is_identifier_generating_function_name(
1466        &self,
1467        _ident: &Ident,
1468        _name_parts: &[ObjectNamePart],
1469    ) -> bool {
1470        false
1471    }
1472
1473    /// Returns true if the dialect supports the `x NOTNULL`
1474    /// operator expression.
1475    fn supports_notnull_operator(&self) -> bool {
1476        false
1477    }
1478
1479    /// Returns true if this dialect allows an optional `SIGNED` suffix after integer data types.
1480    ///
1481    /// Example:
1482    /// ```sql
1483    /// CREATE TABLE t (i INT(20) SIGNED);
1484    /// ```
1485    ///
1486    /// Note that this is canonicalized to `INT(20)`.
1487    fn supports_data_type_signed_suffix(&self) -> bool {
1488        false
1489    }
1490
1491    /// Returns true if the dialect supports the `INTERVAL` data type with [Postgres]-style options.
1492    ///
1493    /// Examples:
1494    /// ```sql
1495    /// CREATE TABLE t (i INTERVAL YEAR TO MONTH);
1496    /// SELECT '1 second'::INTERVAL HOUR TO SECOND(3);
1497    /// ```
1498    ///
1499    /// See [`crate::ast::DataType::Interval`] and [`crate::ast::IntervalFields`].
1500    ///
1501    /// [Postgres]: https://www.postgresql.org/docs/17/datatype-datetime.html
1502    fn supports_interval_options(&self) -> bool {
1503        false
1504    }
1505
1506    /// Returns true if the dialect supports specifying which table to copy
1507    /// the schema from inside parenthesis.
1508    ///
1509    /// Not parenthesized:
1510    /// '''sql
1511    /// CREATE TABLE new LIKE old ...
1512    /// '''
1513    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
1514    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
1515    ///
1516    /// Parenthesized:
1517    /// '''sql
1518    /// CREATE TABLE new (LIKE old ...)
1519    /// '''
1520    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
1521    fn supports_create_table_like_parenthesized(&self) -> bool {
1522        false
1523    }
1524
1525    /// Returns true if the dialect supports `SEMANTIC_VIEW()` table functions.
1526    ///
1527    /// ```sql
1528    /// SELECT * FROM SEMANTIC_VIEW(
1529    ///     model_name
1530    ///     DIMENSIONS customer.name, customer.region
1531    ///     METRICS orders.revenue, orders.count
1532    ///     WHERE customer.active = true
1533    /// )
1534    /// ```
1535    fn supports_semantic_view_table_factor(&self) -> bool {
1536        false
1537    }
1538
1539    /// Support quote delimited string literals, e.g. `Q'{...}'`
1540    ///
1541    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Literals.html#GUID-1824CBAA-6E16-4921-B2A6-112FB02248DA)
1542    fn supports_quote_delimited_string(&self) -> bool {
1543        false
1544    }
1545
1546    /// Returns `true` if the dialect supports query optimizer hints in the
1547    /// format of single and multi line comments immediately following a
1548    /// `SELECT`, `INSERT`, `REPLACE`, `DELETE`, or `MERGE` keyword.
1549    ///
1550    /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html)
1551    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Comments.html#SQLRF-GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
1552    fn supports_comment_optimizer_hint(&self) -> bool {
1553        false
1554    }
1555
1556    /// Returns true if the dialect considers the `&&` operator as a boolean AND operator.
1557    fn supports_double_ampersand_operator(&self) -> bool {
1558        false
1559    }
1560
1561    /// Returns true if the dialect supports casting an expression to a binary type
1562    /// using the `BINARY <expr>` syntax.
1563    fn supports_binary_kw_as_cast(&self) -> bool {
1564        false
1565    }
1566
1567    /// Returns true if this dialect supports the `REPLACE` option in a
1568    /// `SELECT *` wildcard expression.
1569    ///
1570    /// Example:
1571    /// ```sql
1572    /// SELECT * REPLACE (col1 AS col1_alias) FROM table;
1573    /// ```
1574    ///
1575    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace)
1576    /// [ClickHouse](https://clickhouse.com/docs/sql-reference/statements/select#replace)
1577    /// [DuckDB](https://duckdb.org/docs/sql/query_syntax/select#replace-clause)
1578    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
1579    fn supports_select_wildcard_replace(&self) -> bool {
1580        false
1581    }
1582
1583    /// Returns true if this dialect supports the `ILIKE` option in a
1584    /// `SELECT *` wildcard expression.
1585    ///
1586    /// Example:
1587    /// ```sql
1588    /// SELECT * ILIKE '%pattern%' FROM table;
1589    /// ```
1590    ///
1591    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
1592    fn supports_select_wildcard_ilike(&self) -> bool {
1593        false
1594    }
1595
1596    /// Returns true if this dialect supports the `RENAME` option in a
1597    /// `SELECT *` wildcard expression.
1598    ///
1599    /// Example:
1600    /// ```sql
1601    /// SELECT * RENAME col1 AS col1_alias FROM table;
1602    /// ```
1603    ///
1604    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
1605    fn supports_select_wildcard_rename(&self) -> bool {
1606        false
1607    }
1608
1609    /// Returns true if this dialect supports aliasing a wildcard select item.
1610    ///
1611    /// Example:
1612    /// ```sql
1613    /// SELECT t.* alias FROM t
1614    /// SELECT t.* AS alias FROM t
1615    /// ```
1616    fn supports_select_wildcard_with_alias(&self) -> bool {
1617        false
1618    }
1619
1620    /// Returns true if this dialect supports the `OPTIMIZE TABLE` statement.
1621    ///
1622    /// Example:
1623    /// ```sql
1624    /// OPTIMIZE TABLE table_name;
1625    /// ```
1626    ///
1627    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
1628    fn supports_optimize_table(&self) -> bool {
1629        false
1630    }
1631
1632    /// Returns true if this dialect supports the `INSTALL` statement.
1633    ///
1634    /// Example:
1635    /// ```sql
1636    /// INSTALL extension_name;
1637    /// ```
1638    ///
1639    /// [DuckDB](https://duckdb.org/docs/extensions/overview)
1640    fn supports_install(&self) -> bool {
1641        false
1642    }
1643
1644    /// Returns true if this dialect supports the `DETACH` statement.
1645    ///
1646    /// Example:
1647    /// ```sql
1648    /// DETACH DATABASE db_name;
1649    /// ```
1650    ///
1651    /// [DuckDB](https://duckdb.org/docs/sql/statements/attach#detach-syntax)
1652    fn supports_detach(&self) -> bool {
1653        false
1654    }
1655
1656    /// Returns true if this dialect supports the `PREWHERE` clause
1657    /// in `SELECT` statements.
1658    ///
1659    /// Example:
1660    /// ```sql
1661    /// SELECT * FROM table PREWHERE col > 0 WHERE col < 100;
1662    /// ```
1663    ///
1664    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere)
1665    fn supports_prewhere(&self) -> bool {
1666        false
1667    }
1668
1669    /// Returns true if this dialect supports the `WITH FILL` clause
1670    /// in `ORDER BY` expressions.
1671    ///
1672    /// Example:
1673    /// ```sql
1674    /// SELECT * FROM table ORDER BY col WITH FILL FROM 1 TO 10 STEP 1;
1675    /// ```
1676    ///
1677    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier)
1678    fn supports_with_fill(&self) -> bool {
1679        false
1680    }
1681
1682    /// Returns true if this dialect supports the `LIMIT BY` clause.
1683    ///
1684    /// Example:
1685    /// ```sql
1686    /// SELECT * FROM table LIMIT 10 BY col;
1687    /// ```
1688    ///
1689    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/limit-by)
1690    fn supports_limit_by(&self) -> bool {
1691        false
1692    }
1693
1694    /// Returns true if this dialect supports the `INTERPOLATE` clause
1695    /// in `ORDER BY` expressions.
1696    ///
1697    /// Example:
1698    /// ```sql
1699    /// SELECT * FROM table ORDER BY col WITH FILL INTERPOLATE (col2 AS col2 + 1);
1700    /// ```
1701    ///
1702    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier)
1703    fn supports_interpolate(&self) -> bool {
1704        false
1705    }
1706
1707    /// Returns true if this dialect supports the `SETTINGS` clause.
1708    ///
1709    /// Example:
1710    /// ```sql
1711    /// SELECT * FROM table SETTINGS max_threads = 4;
1712    /// ```
1713    ///
1714    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
1715    fn supports_settings(&self) -> bool {
1716        false
1717    }
1718
1719    /// Returns true if this dialect supports the `FORMAT` clause in `SELECT` statements.
1720    ///
1721    /// Example:
1722    /// ```sql
1723    /// SELECT * FROM table FORMAT JSON;
1724    /// ```
1725    ///
1726    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/format)
1727    fn supports_select_format(&self) -> bool {
1728        false
1729    }
1730
1731    /// Returns true if the dialect supports the two-argument comma-separated
1732    /// form of the `TRIM` function: `TRIM(expr, characters)`.
1733    fn supports_comma_separated_trim(&self) -> bool {
1734        false
1735    }
1736
1737    /// Returns true if the dialect supports the `AS` keyword being
1738    /// optional in a CTE definition. For example:
1739    /// ```sql
1740    /// WITH cte_name (SELECT ...)
1741    /// ```
1742    ///
1743    /// [Databricks](https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-qry-select-cte)
1744    fn supports_cte_without_as(&self) -> bool {
1745        false
1746    }
1747
1748    /// Returns true if the dialect supports parenthesized multi-column
1749    /// aliases in SELECT items. For example:
1750    /// ```sql
1751    /// SELECT stack(2, 'a', 'b') AS (col1, col2)
1752    /// ```
1753    ///
1754    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select.html)
1755    fn supports_select_item_multi_column_alias(&self) -> bool {
1756        false
1757    }
1758
1759    /// Returns true if the dialect supports XML-related expressions
1760    /// such as `xml '<foo/>'` typed strings, XML functions like
1761    /// `XMLCONCAT`, `XMLELEMENT`, etc.
1762    ///
1763    /// When this returns false, `xml` is treated as a regular identifier.
1764    ///
1765    /// [PostgreSQL](https://www.postgresql.org/docs/current/functions-xml.html)
1766    fn supports_xml_expressions(&self) -> bool {
1767        false
1768    }
1769
1770    /// Returns true if the dialect supports `USING <format>` in `CREATE TABLE`.
1771    ///
1772    /// Example:
1773    /// ```sql
1774    /// CREATE TABLE t (i INT) USING PARQUET
1775    /// ```
1776    ///
1777    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html)
1778    fn supports_create_table_using(&self) -> bool {
1779        false
1780    }
1781
1782    /// Returns true if the dialect treats `LONG` as an alias for `BIGINT`.
1783    ///
1784    /// Example:
1785    /// ```sql
1786    /// CREATE TABLE t (id LONG)
1787    /// ```
1788    ///
1789    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-datatypes.html)
1790    fn supports_long_type_as_bigint(&self) -> bool {
1791        false
1792    }
1793
1794    /// Returns true if the dialect supports `MAP<K, V>` angle-bracket syntax for the MAP data type.
1795    ///
1796    /// Example:
1797    /// ```sql
1798    /// CREATE TABLE t (m MAP<STRING, INT>)
1799    /// ```
1800    ///
1801    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-datatypes.html)
1802    fn supports_map_literal_with_angle_brackets(&self) -> bool {
1803        false
1804    }
1805}
1806
1807/// Operators for which precedence must be defined.
1808///
1809/// Higher number -> higher precedence.
1810/// See expression parsing for how these values are used.
1811#[derive(Debug, Clone, Copy)]
1812pub enum Precedence {
1813    /// Member access operator `.` (highest precedence).
1814    Period,
1815    /// Postgres style type cast `::`.
1816    DoubleColon,
1817    /// Timezone operator (e.g. `AT TIME ZONE`).
1818    AtTz,
1819    /// Multiplication / Division / Modulo operators (`*`, `/`, `%`).
1820    MulDivModOp,
1821    /// Addition / Subtraction (`+`, `-`).
1822    PlusMinus,
1823    /// Bitwise `XOR` operator (`^`).
1824    Xor,
1825    /// Bitwise `AND` operator (`&`).
1826    Ampersand,
1827    /// Bitwise `CARET` (^) for some dialects.
1828    Caret,
1829    /// Bitwise `OR` / pipe operator (`|`).
1830    Pipe,
1831    /// `:` operator for json/variant access.
1832    Colon,
1833    /// `BETWEEN` operator.
1834    Between,
1835    /// Equality operator (`=`).
1836    Eq,
1837    /// Pattern matching (`LIKE`).
1838    Like,
1839    /// `IS` operator (e.g. `IS NULL`).
1840    Is,
1841    /// Other Postgres-specific operators.
1842    PgOther,
1843    /// Unary `NOT`.
1844    UnaryNot,
1845    /// Logical `AND`.
1846    And,
1847    /// Logical `OR` (lowest precedence).
1848    Or,
1849}
1850
1851impl dyn Dialect {
1852    /// Returns true if `self` is the concrete dialect `T`.
1853    #[inline]
1854    pub fn is<T: Dialect>(&self) -> bool {
1855        // borrowed from `Any` implementation
1856        TypeId::of::<T>() == self.dialect()
1857    }
1858}
1859
1860/// Returns the built in [`Dialect`] corresponding to `dialect_name`.
1861///
1862/// See [`Dialect`] documentation for an example.
1863pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect>> {
1864    let dialect_name = dialect_name.as_ref();
1865    match dialect_name.to_lowercase().as_str() {
1866        "generic" => Some(Box::new(GenericDialect)),
1867        "mysql" => Some(Box::new(MySqlDialect {})),
1868        "postgresql" | "postgres" => Some(Box::new(PostgreSqlDialect {})),
1869        "hive" => Some(Box::new(HiveDialect {})),
1870        "sqlite" => Some(Box::new(SQLiteDialect {})),
1871        "snowflake" => Some(Box::new(SnowflakeDialect)),
1872        "redshift" => Some(Box::new(RedshiftSqlDialect {})),
1873        "mssql" => Some(Box::new(MsSqlDialect {})),
1874        "clickhouse" => Some(Box::new(ClickHouseDialect {})),
1875        "bigquery" => Some(Box::new(BigQueryDialect)),
1876        "ansi" => Some(Box::new(AnsiDialect {})),
1877        "duckdb" => Some(Box::new(DuckDbDialect {})),
1878        "databricks" => Some(Box::new(DatabricksDialect {})),
1879        "spark" | "sparksql" => Some(Box::new(SparkSqlDialect {})),
1880        "oracle" => Some(Box::new(OracleDialect {})),
1881        "teradata" => Some(Box::new(TeradataDialect {})),
1882        _ => None,
1883    }
1884}
1885
1886#[cfg(test)]
1887mod tests {
1888    use super::*;
1889
1890    struct DialectHolder<'a> {
1891        dialect: &'a dyn Dialect,
1892    }
1893
1894    #[test]
1895    fn test_is_dialect() {
1896        let generic_dialect: &dyn Dialect = &GenericDialect {};
1897        let ansi_dialect: &dyn Dialect = &AnsiDialect {};
1898
1899        let generic_holder = DialectHolder {
1900            dialect: generic_dialect,
1901        };
1902        let ansi_holder = DialectHolder {
1903            dialect: ansi_dialect,
1904        };
1905
1906        assert!(dialect_of!(generic_holder is GenericDialect |  AnsiDialect),);
1907        assert!(!dialect_of!(generic_holder is  AnsiDialect));
1908        assert!(dialect_of!(ansi_holder is AnsiDialect));
1909        assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
1910        assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
1911    }
1912
1913    #[test]
1914    fn test_dialect_from_str() {
1915        assert!(parse_dialect("generic").is::<GenericDialect>());
1916        assert!(parse_dialect("mysql").is::<MySqlDialect>());
1917        assert!(parse_dialect("MySql").is::<MySqlDialect>());
1918        assert!(parse_dialect("postgresql").is::<PostgreSqlDialect>());
1919        assert!(parse_dialect("postgres").is::<PostgreSqlDialect>());
1920        assert!(parse_dialect("hive").is::<HiveDialect>());
1921        assert!(parse_dialect("sqlite").is::<SQLiteDialect>());
1922        assert!(parse_dialect("snowflake").is::<SnowflakeDialect>());
1923        assert!(parse_dialect("SnowFlake").is::<SnowflakeDialect>());
1924        assert!(parse_dialect("MsSql").is::<MsSqlDialect>());
1925        assert!(parse_dialect("clickhouse").is::<ClickHouseDialect>());
1926        assert!(parse_dialect("ClickHouse").is::<ClickHouseDialect>());
1927        assert!(parse_dialect("bigquery").is::<BigQueryDialect>());
1928        assert!(parse_dialect("BigQuery").is::<BigQueryDialect>());
1929        assert!(parse_dialect("ansi").is::<AnsiDialect>());
1930        assert!(parse_dialect("ANSI").is::<AnsiDialect>());
1931        assert!(parse_dialect("duckdb").is::<DuckDbDialect>());
1932        assert!(parse_dialect("DuckDb").is::<DuckDbDialect>());
1933        assert!(parse_dialect("DataBricks").is::<DatabricksDialect>());
1934        assert!(parse_dialect("databricks").is::<DatabricksDialect>());
1935        assert!(parse_dialect("teradata").is::<TeradataDialect>());
1936        assert!(parse_dialect("Teradata").is::<TeradataDialect>());
1937
1938        // error cases
1939        assert!(dialect_from_str("Unknown").is_none());
1940        assert!(dialect_from_str("").is_none());
1941    }
1942
1943    fn parse_dialect(v: &str) -> Box<dyn Dialect> {
1944        dialect_from_str(v).unwrap()
1945    }
1946
1947    #[test]
1948    #[cfg(feature = "derive-dialect")]
1949    fn test_dialect_override() {
1950        derive_dialect!(EnhancedGenericDialect, GenericDialect,
1951            preserve_type_id = true,
1952            overrides = {
1953                supports_order_by_all = true,
1954                supports_nested_comments = true,
1955                supports_triple_quoted_string = true,
1956            },
1957        );
1958        let dialect = EnhancedGenericDialect::new();
1959
1960        assert!(dialect.supports_order_by_all());
1961        assert!(dialect.supports_nested_comments());
1962        assert!(dialect.supports_triple_quoted_string());
1963
1964        let d: &dyn Dialect = &dialect;
1965        assert!(d.is::<GenericDialect>());
1966    }
1967
1968    #[test]
1969    fn identifier_quote_style() {
1970        let tests: Vec<(&dyn Dialect, &str, Option<char>)> = vec![
1971            (&GenericDialect {}, "id", None),
1972            (&SQLiteDialect {}, "id", Some('`')),
1973            (&PostgreSqlDialect {}, "id", Some('"')),
1974        ];
1975
1976        for (dialect, ident, expected) in tests {
1977            let actual = dialect.identifier_quote_style(ident);
1978
1979            assert_eq!(actual, expected);
1980        }
1981    }
1982
1983    #[test]
1984    fn parse_with_wrapped_dialect() {
1985        /// Wrapper for a dialect. In a real-world example, this wrapper
1986        /// would tweak the behavior of the dialect. For the test case,
1987        /// it wraps all methods unaltered.
1988        #[derive(Debug)]
1989        struct WrappedDialect(MySqlDialect);
1990
1991        impl Dialect for WrappedDialect {
1992            fn dialect(&self) -> std::any::TypeId {
1993                self.0.dialect()
1994            }
1995
1996            fn is_identifier_start(&self, ch: char) -> bool {
1997                self.0.is_identifier_start(ch)
1998            }
1999
2000            fn is_delimited_identifier_start(&self, ch: char) -> bool {
2001                self.0.is_delimited_identifier_start(ch)
2002            }
2003
2004            fn is_nested_delimited_identifier_start(&self, ch: char) -> bool {
2005                self.0.is_nested_delimited_identifier_start(ch)
2006            }
2007
2008            fn peek_nested_delimited_identifier_quotes(
2009                &self,
2010                chars: std::iter::Peekable<std::str::Chars<'_>>,
2011            ) -> Option<(char, Option<char>)> {
2012                self.0.peek_nested_delimited_identifier_quotes(chars)
2013            }
2014
2015            fn identifier_quote_style(&self, identifier: &str) -> Option<char> {
2016                self.0.identifier_quote_style(identifier)
2017            }
2018
2019            fn supports_string_literal_backslash_escape(&self) -> bool {
2020                self.0.supports_string_literal_backslash_escape()
2021            }
2022
2023            fn supports_filter_during_aggregation(&self) -> bool {
2024                self.0.supports_filter_during_aggregation()
2025            }
2026
2027            fn supports_within_after_array_aggregation(&self) -> bool {
2028                self.0.supports_within_after_array_aggregation()
2029            }
2030
2031            fn supports_group_by_expr(&self) -> bool {
2032                self.0.supports_group_by_expr()
2033            }
2034
2035            fn supports_in_empty_list(&self) -> bool {
2036                self.0.supports_in_empty_list()
2037            }
2038
2039            fn convert_type_before_value(&self) -> bool {
2040                self.0.convert_type_before_value()
2041            }
2042
2043            fn parse_prefix(
2044                &self,
2045                parser: &mut sqlparser::parser::Parser,
2046            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
2047                self.0.parse_prefix(parser)
2048            }
2049
2050            fn parse_infix(
2051                &self,
2052                parser: &mut sqlparser::parser::Parser,
2053                expr: &Expr,
2054                precedence: u8,
2055            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
2056                self.0.parse_infix(parser, expr, precedence)
2057            }
2058
2059            fn get_next_precedence(
2060                &self,
2061                parser: &sqlparser::parser::Parser,
2062            ) -> Option<Result<u8, sqlparser::parser::ParserError>> {
2063                self.0.get_next_precedence(parser)
2064            }
2065
2066            fn parse_statement(
2067                &self,
2068                parser: &mut sqlparser::parser::Parser,
2069            ) -> Option<Result<Statement, sqlparser::parser::ParserError>> {
2070                self.0.parse_statement(parser)
2071            }
2072
2073            fn is_identifier_part(&self, ch: char) -> bool {
2074                self.0.is_identifier_part(ch)
2075            }
2076        }
2077
2078        #[allow(clippy::needless_raw_string_hashes)]
2079        let statement = r#"SELECT 'Wayne\'s World'"#;
2080        let res1 = Parser::parse_sql(&MySqlDialect {}, statement);
2081        let res2 = Parser::parse_sql(&WrappedDialect(MySqlDialect {}), statement);
2082        assert!(res1.is_ok());
2083        assert_eq!(res1, res2);
2084    }
2085}