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