[Go to site: main page, start]

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 supports PartiQL for querying semi-structured data
1228    /// <https://partiql.org/index.html>
1229    fn supports_partiql(&self) -> bool {
1230        false
1231    }
1232
1233    /// Returns true if the dialect supports the `CONSTRAINT` keyword without a name
1234    /// in table constraint definitions.
1235    ///
1236    /// Example:
1237    /// ```sql
1238    /// CREATE TABLE t (a INT, CONSTRAINT CHECK (a > 0))
1239    /// ```
1240    ///
1241    /// This is a MySQL extension; the SQL standard requires a name after `CONSTRAINT`.
1242    /// When the name is omitted, the output normalizes to just the constraint type
1243    /// without the `CONSTRAINT` keyword (e.g., `CHECK (a > 0)`).
1244    ///
1245    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1246    fn supports_constraint_keyword_without_name(&self) -> bool {
1247        false
1248    }
1249
1250    /// Returns true if the dialect supports the `KEY` keyword as part of
1251    /// column-level constraints in a `CREATE TABLE` statement.
1252    ///
1253    /// When enabled, the parser accepts these MySQL-specific column options:
1254    /// - `UNIQUE [KEY]` — optional `KEY` after `UNIQUE`
1255    /// - `[PRIMARY] KEY` — standalone `KEY` as shorthand for `PRIMARY KEY`
1256    ///
1257    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1258    fn supports_key_column_option(&self) -> bool {
1259        false
1260    }
1261
1262    /// Returns true if the specified keyword is reserved and cannot be
1263    /// used as an identifier without special handling like quoting.
1264    fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
1265        keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
1266    }
1267
1268    /// Returns reserved keywords that may prefix a select item expression
1269    /// e.g. `SELECT CONNECT_BY_ROOT name FROM Tbl2` (Snowflake)
1270    fn get_reserved_keywords_for_select_item_operator(&self) -> &[Keyword] {
1271        &[]
1272    }
1273
1274    /// Returns grantee types that should be treated as identifiers
1275    fn get_reserved_grantees_types(&self) -> &[GranteesType] {
1276        &[]
1277    }
1278
1279    /// Returns true if this dialect supports the `TABLESAMPLE` option
1280    /// before the table alias option. For example:
1281    ///
1282    /// Table sample before alias: `SELECT * FROM tbl AS t TABLESAMPLE (10)`
1283    /// Table sample after alias: `SELECT * FROM tbl TABLESAMPLE (10) AS t`
1284    ///
1285    /// <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#_7_6_table_reference>
1286    fn supports_table_sample_before_alias(&self) -> bool {
1287        false
1288    }
1289
1290    /// Returns true if this dialect supports the `INSERT INTO ... SET col1 = 1, ...` syntax.
1291    ///
1292    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/insert.html>
1293    fn supports_insert_set(&self) -> bool {
1294        false
1295    }
1296
1297    /// Does the dialect support table function in insertion?
1298    fn supports_insert_table_function(&self) -> bool {
1299        false
1300    }
1301
1302    /// Does the dialect support table queries in insertion?
1303    ///
1304    /// e.g. `SELECT INTO (<query>) ...`
1305    fn supports_insert_table_query(&self) -> bool {
1306        false
1307    }
1308
1309    /// Does the dialect support insert formats, e.g. `INSERT INTO ... FORMAT <format>`
1310    fn supports_insert_format(&self) -> bool {
1311        false
1312    }
1313
1314    /// Returns true if this dialect supports `INSERT INTO t [[AS] alias] ...`.
1315    fn supports_insert_table_alias(&self) -> bool {
1316        false
1317    }
1318
1319    /// Returns true if this dialect supports `SET` statements without an explicit
1320    /// assignment operator such as `=`. For example: `SET SHOWPLAN_XML ON`.
1321    fn supports_set_stmt_without_operator(&self) -> bool {
1322        false
1323    }
1324
1325    /// Returns true if the specified keyword should be parsed as a column identifier.
1326    /// See [keywords::RESERVED_FOR_COLUMN_ALIAS]
1327    fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1328        !keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw)
1329    }
1330
1331    /// Returns true if the specified keyword should be parsed as a select item alias.
1332    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
1333    /// to enable looking ahead if needed.
1334    fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1335        explicit || self.is_column_alias(kw, parser)
1336    }
1337
1338    /// Returns true if the specified keyword should be parsed as a table factor identifier.
1339    /// See [keywords::RESERVED_FOR_TABLE_FACTOR]
1340    fn is_table_factor(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1341        !keywords::RESERVED_FOR_TABLE_FACTOR.contains(kw)
1342    }
1343
1344    /// Returns true if the specified keyword should be parsed as a table factor alias.
1345    /// See [keywords::RESERVED_FOR_TABLE_ALIAS]
1346    fn is_table_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1347        !keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
1348    }
1349
1350    /// Returns true if the specified keyword should be parsed as a table factor alias.
1351    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
1352    /// to enable looking ahead if needed.
1353    fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1354        explicit || self.is_table_alias(kw, parser)
1355    }
1356
1357    /// Returns true if this dialect supports querying historical table data
1358    /// by specifying which version of the data to query.
1359    fn supports_table_versioning(&self) -> bool {
1360        false
1361    }
1362
1363    /// Returns true if this dialect supports the E'...' syntax for string literals
1364    ///
1365    /// Postgres: <https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE>
1366    fn supports_string_escape_constant(&self) -> bool {
1367        false
1368    }
1369
1370    /// Returns true if the dialect supports the table hints in the `FROM` clause.
1371    fn supports_table_hints(&self) -> bool {
1372        false
1373    }
1374
1375    /// Returns true if this dialect requires a whitespace character after `--` to start a single line comment.
1376    ///
1377    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/ansi-diff-comments.html>
1378    /// e.g. UPDATE account SET balance=balance--1
1379    //       WHERE account_id=5752             ^^^ will be interpreted as two minus signs instead of a comment
1380    fn requires_single_line_comment_whitespace(&self) -> bool {
1381        false
1382    }
1383
1384    /// Returns true if the dialect supports array type definition with brackets with
1385    /// an optional size. For example:
1386    /// ```CREATE TABLE my_table (arr1 INT[], arr2 INT[3])```
1387    /// ```SELECT x::INT[]```
1388    fn supports_array_typedef_with_brackets(&self) -> bool {
1389        false
1390    }
1391    /// Returns true if the dialect supports geometric types.
1392    ///
1393    /// Postgres: <https://www.postgresql.org/docs/9.5/functions-geometry.html>
1394    /// e.g. @@ circle '((0,0),10)'
1395    fn supports_geometric_types(&self) -> bool {
1396        false
1397    }
1398
1399    /// Returns true if the dialect supports `ORDER BY ALL`.
1400    /// `ALL` which means all columns of the SELECT clause.
1401    ///
1402    /// For example: ```SELECT * FROM addresses ORDER BY ALL;```.
1403    fn supports_order_by_all(&self) -> bool {
1404        false
1405    }
1406
1407    /// Returns true if the dialect supports `SET NAMES <charset_name> [COLLATE <collation_name>]`.
1408    ///
1409    /// - [MySQL](https://dev.mysql.com/doc/refman/8.4/en/set-names.html)
1410    /// - [PostgreSQL](https://www.postgresql.org/docs/17/sql-set.html)
1411    ///
1412    /// Note: Postgres doesn't support the `COLLATE` clause, but we permissively parse it anyway.
1413    fn supports_set_names(&self) -> bool {
1414        false
1415    }
1416
1417    /// Returns true if the dialect supports space-separated column options
1418    /// in a `CREATE TABLE` statement. For example:
1419    /// ```sql
1420    /// CREATE TABLE tbl (
1421    ///     col INT NOT NULL DEFAULT 0
1422    /// );
1423    /// ```
1424    fn supports_space_separated_column_options(&self) -> bool {
1425        false
1426    }
1427
1428    /// Returns true if the dialect supports the `USING` clause in an `ALTER COLUMN` statement.
1429    /// Example:
1430    ///  ```sql
1431    ///  ALTER TABLE tbl ALTER COLUMN col SET DATA TYPE <type> USING <exp>`
1432    /// ```
1433    fn supports_alter_column_type_using(&self) -> bool {
1434        false
1435    }
1436
1437    /// Returns true if the dialect supports `ALTER TABLE tbl DROP COLUMN c1, ..., cn`
1438    fn supports_comma_separated_drop_column_list(&self) -> bool {
1439        false
1440    }
1441
1442    /// Returns true if the dialect considers the specified ident as a function
1443    /// that returns an identifier. Typically used to generate identifiers
1444    /// programmatically.
1445    ///
1446    /// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
1447    fn is_identifier_generating_function_name(
1448        &self,
1449        _ident: &Ident,
1450        _name_parts: &[ObjectNamePart],
1451    ) -> bool {
1452        false
1453    }
1454
1455    /// Returns true if the dialect supports the `x NOTNULL`
1456    /// operator expression.
1457    fn supports_notnull_operator(&self) -> bool {
1458        false
1459    }
1460
1461    /// Returns true if this dialect allows an optional `SIGNED` suffix after integer data types.
1462    ///
1463    /// Example:
1464    /// ```sql
1465    /// CREATE TABLE t (i INT(20) SIGNED);
1466    /// ```
1467    ///
1468    /// Note that this is canonicalized to `INT(20)`.
1469    fn supports_data_type_signed_suffix(&self) -> bool {
1470        false
1471    }
1472
1473    /// Returns true if the dialect supports the `INTERVAL` data type with [Postgres]-style options.
1474    ///
1475    /// Examples:
1476    /// ```sql
1477    /// CREATE TABLE t (i INTERVAL YEAR TO MONTH);
1478    /// SELECT '1 second'::INTERVAL HOUR TO SECOND(3);
1479    /// ```
1480    ///
1481    /// See [`crate::ast::DataType::Interval`] and [`crate::ast::IntervalFields`].
1482    ///
1483    /// [Postgres]: https://www.postgresql.org/docs/17/datatype-datetime.html
1484    fn supports_interval_options(&self) -> bool {
1485        false
1486    }
1487
1488    /// Returns true if the dialect supports specifying which table to copy
1489    /// the schema from inside parenthesis.
1490    ///
1491    /// Not parenthesized:
1492    /// '''sql
1493    /// CREATE TABLE new LIKE old ...
1494    /// '''
1495    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
1496    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
1497    ///
1498    /// Parenthesized:
1499    /// '''sql
1500    /// CREATE TABLE new (LIKE old ...)
1501    /// '''
1502    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
1503    fn supports_create_table_like_parenthesized(&self) -> bool {
1504        false
1505    }
1506
1507    /// Returns true if the dialect supports `SEMANTIC_VIEW()` table functions.
1508    ///
1509    /// ```sql
1510    /// SELECT * FROM SEMANTIC_VIEW(
1511    ///     model_name
1512    ///     DIMENSIONS customer.name, customer.region
1513    ///     METRICS orders.revenue, orders.count
1514    ///     WHERE customer.active = true
1515    /// )
1516    /// ```
1517    fn supports_semantic_view_table_factor(&self) -> bool {
1518        false
1519    }
1520
1521    /// Support quote delimited string literals, e.g. `Q'{...}'`
1522    ///
1523    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Literals.html#GUID-1824CBAA-6E16-4921-B2A6-112FB02248DA)
1524    fn supports_quote_delimited_string(&self) -> bool {
1525        false
1526    }
1527
1528    /// Returns `true` if the dialect supports query optimizer hints in the
1529    /// format of single and multi line comments immediately following a
1530    /// `SELECT`, `INSERT`, `REPLACE`, `DELETE`, or `MERGE` keyword.
1531    ///
1532    /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html)
1533    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Comments.html#SQLRF-GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
1534    fn supports_comment_optimizer_hint(&self) -> bool {
1535        false
1536    }
1537
1538    /// Returns true if the dialect considers the `&&` operator as a boolean AND operator.
1539    fn supports_double_ampersand_operator(&self) -> bool {
1540        false
1541    }
1542
1543    /// Returns true if the dialect supports casting an expression to a binary type
1544    /// using the `BINARY <expr>` syntax.
1545    fn supports_binary_kw_as_cast(&self) -> bool {
1546        false
1547    }
1548
1549    /// Returns true if this dialect supports the `REPLACE` option in a
1550    /// `SELECT *` wildcard expression.
1551    ///
1552    /// Example:
1553    /// ```sql
1554    /// SELECT * REPLACE (col1 AS col1_alias) FROM table;
1555    /// ```
1556    ///
1557    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace)
1558    /// [ClickHouse](https://clickhouse.com/docs/sql-reference/statements/select#replace)
1559    /// [DuckDB](https://duckdb.org/docs/sql/query_syntax/select#replace-clause)
1560    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
1561    fn supports_select_wildcard_replace(&self) -> bool {
1562        false
1563    }
1564
1565    /// Returns true if this dialect supports the `ILIKE` option in a
1566    /// `SELECT *` wildcard expression.
1567    ///
1568    /// Example:
1569    /// ```sql
1570    /// SELECT * ILIKE '%pattern%' FROM table;
1571    /// ```
1572    ///
1573    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
1574    fn supports_select_wildcard_ilike(&self) -> bool {
1575        false
1576    }
1577
1578    /// Returns true if this dialect supports the `RENAME` option in a
1579    /// `SELECT *` wildcard expression.
1580    ///
1581    /// Example:
1582    /// ```sql
1583    /// SELECT * RENAME col1 AS col1_alias FROM table;
1584    /// ```
1585    ///
1586    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
1587    fn supports_select_wildcard_rename(&self) -> bool {
1588        false
1589    }
1590
1591    /// Returns true if this dialect supports aliasing a wildcard select item.
1592    ///
1593    /// Example:
1594    /// ```sql
1595    /// SELECT t.* alias FROM t
1596    /// SELECT t.* AS alias FROM t
1597    /// ```
1598    fn supports_select_wildcard_with_alias(&self) -> bool {
1599        false
1600    }
1601
1602    /// Returns true if this dialect supports the `OPTIMIZE TABLE` statement.
1603    ///
1604    /// Example:
1605    /// ```sql
1606    /// OPTIMIZE TABLE table_name;
1607    /// ```
1608    ///
1609    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
1610    fn supports_optimize_table(&self) -> bool {
1611        false
1612    }
1613
1614    /// Returns true if this dialect supports the `INSTALL` statement.
1615    ///
1616    /// Example:
1617    /// ```sql
1618    /// INSTALL extension_name;
1619    /// ```
1620    ///
1621    /// [DuckDB](https://duckdb.org/docs/extensions/overview)
1622    fn supports_install(&self) -> bool {
1623        false
1624    }
1625
1626    /// Returns true if this dialect supports the `DETACH` statement.
1627    ///
1628    /// Example:
1629    /// ```sql
1630    /// DETACH DATABASE db_name;
1631    /// ```
1632    ///
1633    /// [DuckDB](https://duckdb.org/docs/sql/statements/attach#detach-syntax)
1634    fn supports_detach(&self) -> bool {
1635        false
1636    }
1637
1638    /// Returns true if this dialect supports the `PREWHERE` clause
1639    /// in `SELECT` statements.
1640    ///
1641    /// Example:
1642    /// ```sql
1643    /// SELECT * FROM table PREWHERE col > 0 WHERE col < 100;
1644    /// ```
1645    ///
1646    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere)
1647    fn supports_prewhere(&self) -> bool {
1648        false
1649    }
1650
1651    /// Returns true if this dialect supports the `WITH FILL` clause
1652    /// in `ORDER BY` expressions.
1653    ///
1654    /// Example:
1655    /// ```sql
1656    /// SELECT * FROM table ORDER BY col WITH FILL FROM 1 TO 10 STEP 1;
1657    /// ```
1658    ///
1659    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier)
1660    fn supports_with_fill(&self) -> bool {
1661        false
1662    }
1663
1664    /// Returns true if this dialect supports the `LIMIT BY` clause.
1665    ///
1666    /// Example:
1667    /// ```sql
1668    /// SELECT * FROM table LIMIT 10 BY col;
1669    /// ```
1670    ///
1671    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/limit-by)
1672    fn supports_limit_by(&self) -> bool {
1673        false
1674    }
1675
1676    /// Returns true if this dialect supports the `INTERPOLATE` clause
1677    /// in `ORDER BY` expressions.
1678    ///
1679    /// Example:
1680    /// ```sql
1681    /// SELECT * FROM table ORDER BY col WITH FILL INTERPOLATE (col2 AS col2 + 1);
1682    /// ```
1683    ///
1684    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier)
1685    fn supports_interpolate(&self) -> bool {
1686        false
1687    }
1688
1689    /// Returns true if this dialect supports the `SETTINGS` clause.
1690    ///
1691    /// Example:
1692    /// ```sql
1693    /// SELECT * FROM table SETTINGS max_threads = 4;
1694    /// ```
1695    ///
1696    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
1697    fn supports_settings(&self) -> bool {
1698        false
1699    }
1700
1701    /// Returns true if this dialect supports the `FORMAT` clause in `SELECT` statements.
1702    ///
1703    /// Example:
1704    /// ```sql
1705    /// SELECT * FROM table FORMAT JSON;
1706    /// ```
1707    ///
1708    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/format)
1709    fn supports_select_format(&self) -> bool {
1710        false
1711    }
1712
1713    /// Returns true if the dialect supports the two-argument comma-separated
1714    /// form of the `TRIM` function: `TRIM(expr, characters)`.
1715    fn supports_comma_separated_trim(&self) -> bool {
1716        false
1717    }
1718
1719    /// Returns true if the dialect supports the `AS` keyword being
1720    /// optional in a CTE definition. For example:
1721    /// ```sql
1722    /// WITH cte_name (SELECT ...)
1723    /// ```
1724    ///
1725    /// [Databricks](https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-qry-select-cte)
1726    fn supports_cte_without_as(&self) -> bool {
1727        false
1728    }
1729
1730    /// Returns true if the dialect supports parenthesized multi-column
1731    /// aliases in SELECT items. For example:
1732    /// ```sql
1733    /// SELECT stack(2, 'a', 'b') AS (col1, col2)
1734    /// ```
1735    ///
1736    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select.html)
1737    fn supports_select_item_multi_column_alias(&self) -> bool {
1738        false
1739    }
1740
1741    /// Returns true if the dialect supports XML-related expressions
1742    /// such as `xml '<foo/>'` typed strings, XML functions like
1743    /// `XMLCONCAT`, `XMLELEMENT`, etc.
1744    ///
1745    /// When this returns false, `xml` is treated as a regular identifier.
1746    ///
1747    /// [PostgreSQL](https://www.postgresql.org/docs/current/functions-xml.html)
1748    fn supports_xml_expressions(&self) -> bool {
1749        false
1750    }
1751
1752    /// Returns true if the dialect supports `USING <format>` in `CREATE TABLE`.
1753    ///
1754    /// Example:
1755    /// ```sql
1756    /// CREATE TABLE t (i INT) USING PARQUET
1757    /// ```
1758    ///
1759    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html)
1760    fn supports_create_table_using(&self) -> bool {
1761        false
1762    }
1763
1764    /// Returns true if the dialect treats `LONG` as an alias for `BIGINT`.
1765    ///
1766    /// Example:
1767    /// ```sql
1768    /// CREATE TABLE t (id LONG)
1769    /// ```
1770    ///
1771    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-datatypes.html)
1772    fn supports_long_type_as_bigint(&self) -> bool {
1773        false
1774    }
1775
1776    /// Returns true if the dialect supports `MAP<K, V>` angle-bracket syntax for the MAP data type.
1777    ///
1778    /// Example:
1779    /// ```sql
1780    /// CREATE TABLE t (m MAP<STRING, INT>)
1781    /// ```
1782    ///
1783    /// [Spark SQL](https://spark.apache.org/docs/latest/sql-ref-datatypes.html)
1784    fn supports_map_literal_with_angle_brackets(&self) -> bool {
1785        false
1786    }
1787}
1788
1789/// Operators for which precedence must be defined.
1790///
1791/// Higher number -> higher precedence.
1792/// See expression parsing for how these values are used.
1793#[derive(Debug, Clone, Copy)]
1794pub enum Precedence {
1795    /// Member access operator `.` (highest precedence).
1796    Period,
1797    /// Postgres style type cast `::`.
1798    DoubleColon,
1799    /// Timezone operator (e.g. `AT TIME ZONE`).
1800    AtTz,
1801    /// Multiplication / Division / Modulo operators (`*`, `/`, `%`).
1802    MulDivModOp,
1803    /// Addition / Subtraction (`+`, `-`).
1804    PlusMinus,
1805    /// Bitwise `XOR` operator (`^`).
1806    Xor,
1807    /// Bitwise `AND` operator (`&`).
1808    Ampersand,
1809    /// Bitwise `CARET` (^) for some dialects.
1810    Caret,
1811    /// Bitwise `OR` / pipe operator (`|`).
1812    Pipe,
1813    /// `:` operator for json/variant access.
1814    Colon,
1815    /// `BETWEEN` operator.
1816    Between,
1817    /// Equality operator (`=`).
1818    Eq,
1819    /// Pattern matching (`LIKE`).
1820    Like,
1821    /// `IS` operator (e.g. `IS NULL`).
1822    Is,
1823    /// Other Postgres-specific operators.
1824    PgOther,
1825    /// Unary `NOT`.
1826    UnaryNot,
1827    /// Logical `AND`.
1828    And,
1829    /// Logical `OR` (lowest precedence).
1830    Or,
1831}
1832
1833impl dyn Dialect {
1834    /// Returns true if `self` is the concrete dialect `T`.
1835    #[inline]
1836    pub fn is<T: Dialect>(&self) -> bool {
1837        // borrowed from `Any` implementation
1838        TypeId::of::<T>() == self.dialect()
1839    }
1840}
1841
1842/// Returns the built in [`Dialect`] corresponding to `dialect_name`.
1843///
1844/// See [`Dialect`] documentation for an example.
1845pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect>> {
1846    let dialect_name = dialect_name.as_ref();
1847    match dialect_name.to_lowercase().as_str() {
1848        "generic" => Some(Box::new(GenericDialect)),
1849        "mysql" => Some(Box::new(MySqlDialect {})),
1850        "postgresql" | "postgres" => Some(Box::new(PostgreSqlDialect {})),
1851        "hive" => Some(Box::new(HiveDialect {})),
1852        "sqlite" => Some(Box::new(SQLiteDialect {})),
1853        "snowflake" => Some(Box::new(SnowflakeDialect)),
1854        "redshift" => Some(Box::new(RedshiftSqlDialect {})),
1855        "mssql" => Some(Box::new(MsSqlDialect {})),
1856        "clickhouse" => Some(Box::new(ClickHouseDialect {})),
1857        "bigquery" => Some(Box::new(BigQueryDialect)),
1858        "ansi" => Some(Box::new(AnsiDialect {})),
1859        "duckdb" => Some(Box::new(DuckDbDialect {})),
1860        "databricks" => Some(Box::new(DatabricksDialect {})),
1861        "spark" | "sparksql" => Some(Box::new(SparkSqlDialect {})),
1862        "oracle" => Some(Box::new(OracleDialect {})),
1863        "teradata" => Some(Box::new(TeradataDialect {})),
1864        _ => None,
1865    }
1866}
1867
1868#[cfg(test)]
1869mod tests {
1870    use super::*;
1871
1872    struct DialectHolder<'a> {
1873        dialect: &'a dyn Dialect,
1874    }
1875
1876    #[test]
1877    fn test_is_dialect() {
1878        let generic_dialect: &dyn Dialect = &GenericDialect {};
1879        let ansi_dialect: &dyn Dialect = &AnsiDialect {};
1880
1881        let generic_holder = DialectHolder {
1882            dialect: generic_dialect,
1883        };
1884        let ansi_holder = DialectHolder {
1885            dialect: ansi_dialect,
1886        };
1887
1888        assert!(dialect_of!(generic_holder is GenericDialect |  AnsiDialect),);
1889        assert!(!dialect_of!(generic_holder is  AnsiDialect));
1890        assert!(dialect_of!(ansi_holder is AnsiDialect));
1891        assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
1892        assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
1893    }
1894
1895    #[test]
1896    fn test_dialect_from_str() {
1897        assert!(parse_dialect("generic").is::<GenericDialect>());
1898        assert!(parse_dialect("mysql").is::<MySqlDialect>());
1899        assert!(parse_dialect("MySql").is::<MySqlDialect>());
1900        assert!(parse_dialect("postgresql").is::<PostgreSqlDialect>());
1901        assert!(parse_dialect("postgres").is::<PostgreSqlDialect>());
1902        assert!(parse_dialect("hive").is::<HiveDialect>());
1903        assert!(parse_dialect("sqlite").is::<SQLiteDialect>());
1904        assert!(parse_dialect("snowflake").is::<SnowflakeDialect>());
1905        assert!(parse_dialect("SnowFlake").is::<SnowflakeDialect>());
1906        assert!(parse_dialect("MsSql").is::<MsSqlDialect>());
1907        assert!(parse_dialect("clickhouse").is::<ClickHouseDialect>());
1908        assert!(parse_dialect("ClickHouse").is::<ClickHouseDialect>());
1909        assert!(parse_dialect("bigquery").is::<BigQueryDialect>());
1910        assert!(parse_dialect("BigQuery").is::<BigQueryDialect>());
1911        assert!(parse_dialect("ansi").is::<AnsiDialect>());
1912        assert!(parse_dialect("ANSI").is::<AnsiDialect>());
1913        assert!(parse_dialect("duckdb").is::<DuckDbDialect>());
1914        assert!(parse_dialect("DuckDb").is::<DuckDbDialect>());
1915        assert!(parse_dialect("DataBricks").is::<DatabricksDialect>());
1916        assert!(parse_dialect("databricks").is::<DatabricksDialect>());
1917        assert!(parse_dialect("teradata").is::<TeradataDialect>());
1918        assert!(parse_dialect("Teradata").is::<TeradataDialect>());
1919
1920        // error cases
1921        assert!(dialect_from_str("Unknown").is_none());
1922        assert!(dialect_from_str("").is_none());
1923    }
1924
1925    fn parse_dialect(v: &str) -> Box<dyn Dialect> {
1926        dialect_from_str(v).unwrap()
1927    }
1928
1929    #[test]
1930    #[cfg(feature = "derive-dialect")]
1931    fn test_dialect_override() {
1932        derive_dialect!(EnhancedGenericDialect, GenericDialect,
1933            preserve_type_id = true,
1934            overrides = {
1935                supports_order_by_all = true,
1936                supports_nested_comments = true,
1937                supports_triple_quoted_string = true,
1938            },
1939        );
1940        let dialect = EnhancedGenericDialect::new();
1941
1942        assert!(dialect.supports_order_by_all());
1943        assert!(dialect.supports_nested_comments());
1944        assert!(dialect.supports_triple_quoted_string());
1945
1946        let d: &dyn Dialect = &dialect;
1947        assert!(d.is::<GenericDialect>());
1948    }
1949
1950    #[test]
1951    fn identifier_quote_style() {
1952        let tests: Vec<(&dyn Dialect, &str, Option<char>)> = vec![
1953            (&GenericDialect {}, "id", None),
1954            (&SQLiteDialect {}, "id", Some('`')),
1955            (&PostgreSqlDialect {}, "id", Some('"')),
1956        ];
1957
1958        for (dialect, ident, expected) in tests {
1959            let actual = dialect.identifier_quote_style(ident);
1960
1961            assert_eq!(actual, expected);
1962        }
1963    }
1964
1965    #[test]
1966    fn parse_with_wrapped_dialect() {
1967        /// Wrapper for a dialect. In a real-world example, this wrapper
1968        /// would tweak the behavior of the dialect. For the test case,
1969        /// it wraps all methods unaltered.
1970        #[derive(Debug)]
1971        struct WrappedDialect(MySqlDialect);
1972
1973        impl Dialect for WrappedDialect {
1974            fn dialect(&self) -> std::any::TypeId {
1975                self.0.dialect()
1976            }
1977
1978            fn is_identifier_start(&self, ch: char) -> bool {
1979                self.0.is_identifier_start(ch)
1980            }
1981
1982            fn is_delimited_identifier_start(&self, ch: char) -> bool {
1983                self.0.is_delimited_identifier_start(ch)
1984            }
1985
1986            fn is_nested_delimited_identifier_start(&self, ch: char) -> bool {
1987                self.0.is_nested_delimited_identifier_start(ch)
1988            }
1989
1990            fn peek_nested_delimited_identifier_quotes(
1991                &self,
1992                chars: std::iter::Peekable<std::str::Chars<'_>>,
1993            ) -> Option<(char, Option<char>)> {
1994                self.0.peek_nested_delimited_identifier_quotes(chars)
1995            }
1996
1997            fn identifier_quote_style(&self, identifier: &str) -> Option<char> {
1998                self.0.identifier_quote_style(identifier)
1999            }
2000
2001            fn supports_string_literal_backslash_escape(&self) -> bool {
2002                self.0.supports_string_literal_backslash_escape()
2003            }
2004
2005            fn supports_filter_during_aggregation(&self) -> bool {
2006                self.0.supports_filter_during_aggregation()
2007            }
2008
2009            fn supports_within_after_array_aggregation(&self) -> bool {
2010                self.0.supports_within_after_array_aggregation()
2011            }
2012
2013            fn supports_group_by_expr(&self) -> bool {
2014                self.0.supports_group_by_expr()
2015            }
2016
2017            fn supports_in_empty_list(&self) -> bool {
2018                self.0.supports_in_empty_list()
2019            }
2020
2021            fn convert_type_before_value(&self) -> bool {
2022                self.0.convert_type_before_value()
2023            }
2024
2025            fn parse_prefix(
2026                &self,
2027                parser: &mut sqlparser::parser::Parser,
2028            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
2029                self.0.parse_prefix(parser)
2030            }
2031
2032            fn parse_infix(
2033                &self,
2034                parser: &mut sqlparser::parser::Parser,
2035                expr: &Expr,
2036                precedence: u8,
2037            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
2038                self.0.parse_infix(parser, expr, precedence)
2039            }
2040
2041            fn get_next_precedence(
2042                &self,
2043                parser: &sqlparser::parser::Parser,
2044            ) -> Option<Result<u8, sqlparser::parser::ParserError>> {
2045                self.0.get_next_precedence(parser)
2046            }
2047
2048            fn parse_statement(
2049                &self,
2050                parser: &mut sqlparser::parser::Parser,
2051            ) -> Option<Result<Statement, sqlparser::parser::ParserError>> {
2052                self.0.parse_statement(parser)
2053            }
2054
2055            fn is_identifier_part(&self, ch: char) -> bool {
2056                self.0.is_identifier_part(ch)
2057            }
2058        }
2059
2060        #[allow(clippy::needless_raw_string_hashes)]
2061        let statement = r#"SELECT 'Wayne\'s World'"#;
2062        let res1 = Parser::parse_sql(&MySqlDialect {}, statement);
2063        let res2 = Parser::parse_sql(&WrappedDialect(MySqlDialect {}), statement);
2064        assert!(res1.is_ok());
2065        assert_eq!(res1, res2);
2066    }
2067}