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