mod.rs - source

sqlparser/dialect/

mod.rs

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