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