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 postgresql;
28mod redshift;
29mod snowflake;
30mod sqlite;
31
32use core::any::{Any, TypeId};
33use core::fmt::Debug;
34use core::iter::Peekable;
35use core::str::Chars;
36
37use log::debug;
38
39pub use self::ansi::AnsiDialect;
40pub use self::bigquery::BigQueryDialect;
41pub use self::clickhouse::ClickHouseDialect;
42pub use self::databricks::DatabricksDialect;
43pub use self::duckdb::DuckDbDialect;
44pub use self::generic::GenericDialect;
45pub use self::hive::HiveDialect;
46pub use self::mssql::MsSqlDialect;
47pub use self::mysql::MySqlDialect;
48pub use self::postgresql::PostgreSqlDialect;
49pub use self::redshift::RedshiftSqlDialect;
50pub use self::snowflake::SnowflakeDialect;
51pub use self::sqlite::SQLiteDialect;
52use crate::ast::{ColumnOption, Expr, Statement};
53pub use crate::keywords;
54use crate::keywords::Keyword;
55use crate::parser::{Parser, ParserError};
56use crate::tokenizer::Token;
57
58#[cfg(not(feature = "std"))]
59use alloc::boxed::Box;
60
61/// Convenience check if a [`Parser`] uses a certain dialect.
62///
63/// Note: when possible please the new style, adding a method to the [`Dialect`]
64/// trait rather than using this macro.
65///
66/// The benefits of adding a method on `Dialect` over this macro are:
67/// 1. user defined [`Dialect`]s can customize the parsing behavior
68/// 2. The differences between dialects can be clearly documented in the trait
69///
70/// `dialect_of!(parser is SQLiteDialect |  GenericDialect)` evaluates
71/// to `true` if `parser.dialect` is one of the [`Dialect`]s specified.
72macro_rules! dialect_of {
73    ( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
74        ($($parsed_dialect.dialect.is::<$dialect_type>())||+)
75    };
76}
77
78// Similar to above, but for applying directly against an instance of dialect
79// instead of a struct member named dialect. This avoids lifetime issues when
80// mixing match guards and token references.
81macro_rules! dialect_is {
82    ($dialect:ident is $($dialect_type:ty)|+) => {
83        ($($dialect.is::<$dialect_type>())||+)
84    }
85}
86
87/// Encapsulates the differences between SQL implementations.
88///
89/// # SQL Dialects
90///
91/// SQL implementations deviate from one another, either due to
92/// custom extensions or various historical reasons. This trait
93/// encapsulates the parsing differences between dialects.
94///
95/// [`GenericDialect`] is the most permissive dialect, and parses the union of
96/// all the other dialects, when there is no ambiguity. However, it does not
97/// currently allow `CREATE TABLE` statements without types specified for all
98/// columns; use [`SQLiteDialect`] if you require that.
99///
100/// # Examples
101/// Most users create a [`Dialect`] directly, as shown on the [module
102/// level documentation]:
103///
104/// ```
105/// # use sqlparser::dialect::AnsiDialect;
106/// let dialect = AnsiDialect {};
107/// ```
108///
109/// It is also possible to dynamically create a [`Dialect`] from its
110/// name. For example:
111///
112/// ```
113/// # use sqlparser::dialect::{AnsiDialect, dialect_from_str};
114/// let dialect = dialect_from_str("ansi").unwrap();
115///
116/// // Parsed dialect is an instance of `AnsiDialect`:
117/// assert!(dialect.is::<AnsiDialect>());
118/// ```
119///
120/// [module level documentation]: crate
121pub trait Dialect: Debug + Any {
122    /// Determine the [`TypeId`] of this dialect.
123    ///
124    /// By default, return the same [`TypeId`] as [`Any::type_id`]. Can be overridden
125    /// by dialects that behave like other dialects
126    /// (for example when wrapping a dialect).
127    fn dialect(&self) -> TypeId {
128        self.type_id()
129    }
130
131    /// Determine if a character starts a quoted identifier. The default
132    /// implementation, accepting "double quoted" ids is both ANSI-compliant
133    /// and appropriate for most dialects (with the notable exception of
134    /// MySQL, MS SQL, and sqlite). You can accept one of characters listed
135    /// in `Word::matching_end_quote` here
136    fn is_delimited_identifier_start(&self, ch: char) -> bool {
137        ch == '"' || ch == '`'
138    }
139
140    /// Determine if a character starts a potential nested quoted identifier.
141    /// Example: RedShift supports the following quote styles to all mean the same thing:
142    /// ```sql
143    /// SELECT 1 AS foo;
144    /// SELECT 1 AS "foo";
145    /// SELECT 1 AS [foo];
146    /// SELECT 1 AS ["foo"];
147    /// ```
148    fn is_nested_delimited_identifier_start(&self, _ch: char) -> bool {
149        false
150    }
151
152    /// Only applicable whenever [`Self::is_nested_delimited_identifier_start`] returns true
153    /// If the next sequence of tokens potentially represent a nested identifier, then this method
154    /// returns a tuple containing the outer quote style, and if present, the inner (nested) quote style.
155    ///
156    /// Example (Redshift):
157    /// ```text
158    /// `["foo"]` => Some(`[`, Some(`"`))
159    /// `[foo]` => Some(`[`, None)
160    /// `[0]` => None
161    /// `"foo"` => None
162    /// ```
163    fn peek_nested_delimited_identifier_quotes(
164        &self,
165        mut _chars: Peekable<Chars<'_>>,
166    ) -> Option<(char, Option<char>)> {
167        None
168    }
169
170    /// Return the character used to quote identifiers.
171    fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
172        None
173    }
174
175    /// Determine if a character is a valid start character for an unquoted identifier
176    fn is_identifier_start(&self, ch: char) -> bool;
177
178    /// Determine if a character is a valid unquoted identifier character
179    fn is_identifier_part(&self, ch: char) -> bool;
180
181    /// Most dialects do not have custom operators. Override this method to provide custom operators.
182    fn is_custom_operator_part(&self, _ch: char) -> bool {
183        false
184    }
185
186    /// Determine if the dialect supports escaping characters via '\' in string literals.
187    ///
188    /// Some dialects like BigQuery and Snowflake support this while others like
189    /// Postgres do not. Such that the following is accepted by the former but
190    /// rejected by the latter.
191    /// ```sql
192    /// SELECT 'ab\'cd';
193    /// ```
194    ///
195    /// Conversely, such dialects reject the following statement which
196    /// otherwise would be valid in the other dialects.
197    /// ```sql
198    /// SELECT '\';
199    /// ```
200    fn supports_string_literal_backslash_escape(&self) -> bool {
201        false
202    }
203
204    /// Determine if the dialect supports string literals with `U&` prefix.
205    /// This is used to specify Unicode code points in string literals.
206    /// For example, in PostgreSQL, the following is a valid string literal:
207    /// ```sql
208    /// SELECT U&'\0061\0062\0063';
209    /// ```
210    /// This is equivalent to the string literal `'abc'`.
211    /// See
212    ///  - [Postgres docs](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE)
213    ///  - [H2 docs](http://www.h2database.com/html/grammar.html#string)
214    fn supports_unicode_string_literal(&self) -> bool {
215        false
216    }
217
218    /// Does the dialect support `FILTER (WHERE expr)` for aggregate queries?
219    fn supports_filter_during_aggregation(&self) -> bool {
220        false
221    }
222
223    /// Returns true if the dialect supports referencing another named window
224    /// within a window clause declaration.
225    ///
226    /// Example
227    /// ```sql
228    /// SELECT * FROM mytable
229    /// WINDOW mynamed_window AS another_named_window
230    /// ```
231    fn supports_window_clause_named_window_reference(&self) -> bool {
232        false
233    }
234
235    /// Returns true if the dialect supports `ARRAY_AGG() [WITHIN GROUP (ORDER BY)]` expressions.
236    /// Otherwise, the dialect should expect an `ORDER BY` without the `WITHIN GROUP` clause, e.g. [`ANSI`]
237    ///
238    /// [`ANSI`]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#array-aggregate-function
239    fn supports_within_after_array_aggregation(&self) -> bool {
240        false
241    }
242
243    /// Returns true if the dialects supports `group sets, roll up, or cube` expressions.
244    fn supports_group_by_expr(&self) -> bool {
245        false
246    }
247
248    /// Returns true if the dialects supports `GROUP BY` modifiers prefixed by a `WITH` keyword.
249    /// Example: `GROUP BY value WITH ROLLUP`.
250    fn supports_group_by_with_modifier(&self) -> bool {
251        false
252    }
253
254    /// Returns true if the dialect supports the `(+)` syntax for OUTER JOIN.
255    fn supports_outer_join_operator(&self) -> bool {
256        false
257    }
258
259    /// Returns true if the dialect supports CONNECT BY.
260    fn supports_connect_by(&self) -> bool {
261        false
262    }
263
264    /// Returns true if the dialect supports `EXECUTE IMMEDIATE` statements.
265    fn supports_execute_immediate(&self) -> bool {
266        false
267    }
268
269    /// Returns true if the dialect supports the MATCH_RECOGNIZE operation.
270    fn supports_match_recognize(&self) -> bool {
271        false
272    }
273
274    /// Returns true if the dialect supports `(NOT) IN ()` expressions
275    fn supports_in_empty_list(&self) -> bool {
276        false
277    }
278
279    /// Returns true if the dialect supports `BEGIN {DEFERRED | IMMEDIATE | EXCLUSIVE | TRY | CATCH} [TRANSACTION]` statements
280    fn supports_start_transaction_modifier(&self) -> bool {
281        false
282    }
283
284    /// Returns true if the dialect supports `END {TRY | CATCH}` statements
285    fn supports_end_transaction_modifier(&self) -> bool {
286        false
287    }
288
289    /// Returns true if the dialect supports named arguments of the form `FUN(a = '1', b = '2')`.
290    fn supports_named_fn_args_with_eq_operator(&self) -> bool {
291        false
292    }
293
294    /// Returns true if the dialect supports named arguments of the form `FUN(a : '1', b : '2')`.
295    fn supports_named_fn_args_with_colon_operator(&self) -> bool {
296        false
297    }
298
299    /// Returns true if the dialect supports named arguments of the form `FUN(a := '1', b := '2')`.
300    fn supports_named_fn_args_with_assignment_operator(&self) -> bool {
301        false
302    }
303
304    /// Returns true if the dialect supports named arguments of the form `FUN(a => '1', b => '2')`.
305    fn supports_named_fn_args_with_rarrow_operator(&self) -> bool {
306        true
307    }
308
309    /// Returns true if dialect supports argument name as arbitrary expression.
310    /// e.g. `FUN(LOWER('a'):'1',  b:'2')`
311    /// Such function arguments are represented in the AST by the `FunctionArg::ExprNamed` variant,
312    /// otherwise use the `FunctionArg::Named` variant (compatible reason).
313    fn supports_named_fn_args_with_expr_name(&self) -> bool {
314        false
315    }
316
317    /// Returns true if the dialect supports identifiers starting with a numeric
318    /// prefix such as tables named `59901_user_login`
319    fn supports_numeric_prefix(&self) -> bool {
320        false
321    }
322
323    /// Returns true if the dialect supports numbers containing underscores, e.g. `10_000_000`
324    fn supports_numeric_literal_underscores(&self) -> bool {
325        false
326    }
327
328    /// Returns true if the dialects supports specifying null treatment
329    /// as part of a window function's parameter list as opposed
330    /// to after the parameter list.
331    ///
332    /// i.e The following syntax returns true
333    /// ```sql
334    /// FIRST_VALUE(a IGNORE NULLS) OVER ()
335    /// ```
336    /// while the following syntax returns false
337    /// ```sql
338    /// FIRST_VALUE(a) IGNORE NULLS OVER ()
339    /// ```
340    fn supports_window_function_null_treatment_arg(&self) -> bool {
341        false
342    }
343
344    /// Returns true if the dialect supports defining structs or objects using a
345    /// syntax like `{'x': 1, 'y': 2, 'z': 3}`.
346    fn supports_dictionary_syntax(&self) -> bool {
347        false
348    }
349
350    /// Returns true if the dialect supports defining object using the
351    /// syntax like `Map {1: 10, 2: 20}`.
352    fn support_map_literal_syntax(&self) -> bool {
353        false
354    }
355
356    /// Returns true if the dialect supports lambda functions, for example:
357    ///
358    /// ```sql
359    /// SELECT transform(array(1, 2, 3), x -> x + 1); -- returns [2,3,4]
360    /// ```
361    fn supports_lambda_functions(&self) -> bool {
362        false
363    }
364
365    /// Returns true if the dialect supports the Python-style `lambda x: expr` /
366    /// `lambda x, y: expr` lambda syntax, for example:
367    ///
368    /// ```sql
369    /// SELECT list_transform([1, 2, 3], lambda x: x + 1); -- returns [2, 3, 4]
370    /// ```
371    ///
372    /// DuckDB added this as an alternative to its arrow-form lambdas
373    /// (`supports_lambda_functions`) and is retiring the single-arrow form, so a
374    /// dialect that has arrow lambdas does not necessarily have this: a separate
375    /// method rather than folding it into `supports_lambda_functions` so ClickHouse
376    /// and Databricks — which set that flag for their own arrow-only lambdas — do
377    /// not silently start accepting a syntax neither engine has.
378    ///
379    /// <https://duckdb.org/docs/stable/sql/functions/lambda.html>
380    fn supports_lambda_colon_syntax(&self) -> bool {
381        false
382    }
383
384    /// Returns true if the dialect supports multiple variable assignment
385    /// using parentheses in a `SET` variable declaration.
386    ///
387    /// ```sql
388    /// SET (variable[, ...]) = (expression[, ...]);
389    /// ```
390    fn supports_parenthesized_set_variables(&self) -> bool {
391        false
392    }
393
394    /// Returns true if the dialect supports an `EXCEPT` clause following a
395    /// wildcard in a select list.
396    ///
397    /// For example
398    /// ```sql
399    /// SELECT * EXCEPT order_id FROM orders;
400    /// ```
401    fn supports_select_wildcard_except(&self) -> bool {
402        false
403    }
404
405    /// Returns true if the dialect has a CONVERT function which accepts a type first
406    /// and an expression second, e.g. `CONVERT(varchar, 1)`
407    fn convert_type_before_value(&self) -> bool {
408        false
409    }
410
411    /// Returns true if the dialect supports triple quoted string
412    /// e.g. `"""abc"""`
413    fn supports_triple_quoted_string(&self) -> bool {
414        false
415    }
416
417    /// Dialect-specific prefix parser override
418    fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
419        // return None to fall back to the default behavior
420        None
421    }
422
423    /// Does the dialect support trailing commas around the query?
424    fn supports_trailing_commas(&self) -> bool {
425        false
426    }
427
428    /// Does the dialect support parsing `LIMIT 1, 2` as `LIMIT 2 OFFSET 1`?
429    fn supports_limit_comma(&self) -> bool {
430        false
431    }
432
433    /// Does the dialect support trailing commas in the projection list?
434    fn supports_projection_trailing_commas(&self) -> bool {
435        self.supports_trailing_commas()
436    }
437
438    /// Returns true if the dialect supports trailing commas in the `FROM` clause of a `SELECT` statement.
439    /// Example: `SELECT 1 FROM T, U, LIMIT 1`
440    fn supports_from_trailing_commas(&self) -> bool {
441        false
442    }
443
444    /// Returns true if the dialect supports trailing commas in the
445    /// column definitions list of a `CREATE` statement.
446    /// Example: `CREATE TABLE T (x INT, y TEXT,)`
447    fn supports_column_definition_trailing_commas(&self) -> bool {
448        false
449    }
450
451    /// Returns true if the dialect supports double dot notation for object names
452    ///
453    /// Example
454    /// ```sql
455    /// SELECT * FROM db_name..table_name
456    /// ```
457    fn supports_object_name_double_dot_notation(&self) -> bool {
458        false
459    }
460
461    /// Return true if the dialect supports the STRUCT literal
462    ///
463    /// Example
464    /// ```sql
465    /// SELECT STRUCT(1 as one, 'foo' as foo, false)
466    /// ```
467    fn supports_struct_literal(&self) -> bool {
468        false
469    }
470
471    /// Return true if the dialect supports empty projections in SELECT statements
472    ///
473    /// Example
474    /// ```sql
475    /// SELECT from table_name
476    /// ```
477    fn supports_empty_projections(&self) -> bool {
478        false
479    }
480
481    /// Return true if the dialect supports wildcard expansion on
482    /// arbitrary expressions in projections.
483    ///
484    /// Example:
485    /// ```sql
486    /// SELECT STRUCT<STRING>('foo').* FROM T
487    /// ```
488    fn supports_select_expr_star(&self) -> bool {
489        false
490    }
491
492    /// Return true if the dialect supports "FROM-first" selects.
493    ///
494    /// Example:
495    /// ```sql
496    /// FROM table
497    /// SELECT *
498    /// ```
499    fn supports_from_first_select(&self) -> bool {
500        false
501    }
502
503    /// Does the dialect support MySQL-style `'user'@'host'` grantee syntax?
504    fn supports_user_host_grantee(&self) -> bool {
505        false
506    }
507
508    /// Does the dialect support the `MATCH() AGAINST()` syntax?
509    fn supports_match_against(&self) -> bool {
510        false
511    }
512
513    /// Dialect-specific infix parser override
514    ///
515    /// This method is called to parse the next infix expression.
516    ///
517    /// If `None` is returned, falls back to the default behavior.
518    fn parse_infix(
519        &self,
520        _parser: &mut Parser,
521        _expr: &Expr,
522        _precedence: u8,
523    ) -> Option<Result<Expr, ParserError>> {
524        // return None to fall back to the default behavior
525        None
526    }
527
528    /// Dialect-specific precedence override
529    ///
530    /// This method is called to get the precedence of the next token.
531    ///
532    /// If `None` is returned, falls back to the default behavior.
533    fn get_next_precedence(&self, _parser: &Parser) -> Option<Result<u8, ParserError>> {
534        // return None to fall back to the default behavior
535        None
536    }
537
538    /// Get the precedence of the next token, looking at the full token stream.
539    ///
540    /// A higher number => higher precedence
541    ///
542    /// See [`Self::get_next_precedence`] to override the behavior for just the
543    /// next token.
544    ///
545    /// The default implementation is used for many dialects, but can be
546    /// overridden to provide dialect-specific behavior.
547    fn get_next_precedence_default(&self, parser: &Parser) -> Result<u8, ParserError> {
548        if let Some(precedence) = self.get_next_precedence(parser) {
549            return precedence;
550        }
551        macro_rules! p {
552            ($precedence:ident) => {
553                self.prec_value(Precedence::$precedence)
554            };
555        }
556
557        let token = parser.peek_token();
558        debug!("get_next_precedence_full() {:?}", token);
559        match token.token {
560            Token::Word(w) if w.keyword == Keyword::OR => Ok(p!(Or)),
561            Token::Word(w) if w.keyword == Keyword::AND => Ok(p!(And)),
562            Token::Word(w) if w.keyword == Keyword::XOR => Ok(p!(Xor)),
563
564            Token::Word(w) if w.keyword == Keyword::AT => {
565                match (
566                    parser.peek_nth_token(1).token,
567                    parser.peek_nth_token(2).token,
568                ) {
569                    (Token::Word(w), Token::Word(w2))
570                        if w.keyword == Keyword::TIME && w2.keyword == Keyword::ZONE =>
571                    {
572                        Ok(p!(AtTz))
573                    }
574                    _ => Ok(self.prec_unknown()),
575                }
576            }
577
578            Token::Word(w) if w.keyword == Keyword::NOT => match parser.peek_nth_token(1).token {
579                // The precedence of NOT varies depending on keyword that
580                // follows it. If it is followed by IN, BETWEEN, or LIKE,
581                // it takes on the precedence of those tokens. Otherwise, it
582                // is not an infix operator, and therefore has zero
583                // precedence.
584                Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
585                Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
586                Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
587                Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
588                Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
589                Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
590                Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
591                _ => Ok(self.prec_unknown()),
592            },
593            Token::Word(w) if w.keyword == Keyword::IS => Ok(p!(Is)),
594            Token::Word(w) if w.keyword == Keyword::IN => Ok(p!(Between)),
595            Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(p!(Between)),
596            Token::Word(w) if w.keyword == Keyword::OVERLAPS => Ok(p!(Between)),
597            Token::Word(w) if w.keyword == Keyword::LIKE => Ok(p!(Like)),
598            Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(p!(Like)),
599            Token::Word(w) if w.keyword == Keyword::RLIKE => Ok(p!(Like)),
600            Token::Word(w) if w.keyword == Keyword::REGEXP => Ok(p!(Like)),
601            Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(p!(Like)),
602            Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(p!(Between)),
603            Token::Word(w) if w.keyword == Keyword::DIV => Ok(p!(MulDivModOp)),
604            Token::Period => Ok(p!(Period)),
605            Token::Eq
606            | Token::Lt
607            | Token::LtEq
608            | Token::Neq
609            | Token::Gt
610            | Token::GtEq
611            | Token::DoubleEq
612            | Token::Tilde
613            | Token::TildeAsterisk
614            | Token::ExclamationMarkTilde
615            | Token::ExclamationMarkTildeAsterisk
616            | Token::DoubleTilde
617            | Token::DoubleTildeAsterisk
618            | Token::ExclamationMarkDoubleTilde
619            | Token::ExclamationMarkDoubleTildeAsterisk
620            | Token::Spaceship => Ok(p!(Eq)),
621            Token::Pipe
622            | Token::QuestionMarkDash
623            | Token::DoubleSharp
624            | Token::Overlap
625            | Token::AmpersandLeftAngleBracket
626            | Token::AmpersandRightAngleBracket
627            | Token::QuestionMarkDashVerticalBar
628            | Token::AmpersandLeftAngleBracketVerticalBar
629            | Token::VerticalBarAmpersandRightAngleBracket
630            | Token::TwoWayArrow
631            | Token::LeftAngleBracketCaret
632            | Token::RightAngleBracketCaret
633            | Token::QuestionMarkSharp
634            | Token::QuestionMarkDoubleVerticalBar
635            | Token::QuestionPipe
636            | Token::TildeEqual
637            | Token::AtSign
638            | Token::ShiftLeftVerticalBar
639            | Token::VerticalBarShiftRight => Ok(p!(Pipe)),
640            Token::Caret | Token::Sharp | Token::ShiftRight | Token::ShiftLeft => Ok(p!(Caret)),
641            Token::Ampersand => Ok(p!(Ampersand)),
642            Token::Plus | Token::Minus => Ok(p!(PlusMinus)),
643            Token::Mul | Token::Div | Token::DuckIntDiv | Token::Mod | Token::StringConcat => {
644                Ok(p!(MulDivModOp))
645            }
646            Token::DoubleColon | Token::ExclamationMark | Token::LBracket | Token::CaretAt => {
647                Ok(p!(DoubleColon))
648            }
649            Token::Arrow
650            | Token::LongArrow
651            | Token::HashArrow
652            | Token::HashLongArrow
653            | Token::AtArrow
654            | Token::ArrowAt
655            | Token::HashMinus
656            | Token::AtQuestion
657            | Token::AtAt
658            | Token::Question
659            | Token::QuestionAnd
660            | Token::CustomBinaryOperator(_) => Ok(p!(PgOther)),
661            _ => Ok(self.prec_unknown()),
662        }
663    }
664
665    /// Dialect-specific statement parser override
666    ///
667    /// This method is called to parse the next statement.
668    ///
669    /// If `None` is returned, falls back to the default behavior.
670    fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
671        // return None to fall back to the default behavior
672        None
673    }
674
675    /// Dialect-specific column option parser override
676    ///
677    /// This method is called to parse the next column option.
678    ///
679    /// If `None` is returned, falls back to the default behavior.
680    fn parse_column_option(
681        &self,
682        _parser: &mut Parser,
683    ) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
684        // return None to fall back to the default behavior
685        Ok(None)
686    }
687
688    /// Decide the lexical Precedence of operators.
689    ///
690    /// Uses (APPROXIMATELY) <https://www.postgresql.org/docs/7.0/operators.htm#AEN2026> as a reference
691    fn prec_value(&self, prec: Precedence) -> u8 {
692        match prec {
693            Precedence::Period => 100,
694            Precedence::DoubleColon => 50,
695            Precedence::AtTz => 41,
696            Precedence::MulDivModOp => 40,
697            Precedence::PlusMinus => 30,
698            Precedence::Xor => 24,
699            Precedence::Ampersand => 23,
700            Precedence::Caret => 22,
701            Precedence::Pipe => 21,
702            Precedence::Between => 20,
703            Precedence::Eq => 20,
704            Precedence::Like => 19,
705            Precedence::Is => 17,
706            Precedence::PgOther => 16,
707            Precedence::UnaryNot => 15,
708            Precedence::And => 10,
709            Precedence::Or => 5,
710        }
711    }
712
713    /// Returns the precedence when the precedence is otherwise unknown
714    fn prec_unknown(&self) -> u8 {
715        0
716    }
717
718    /// Returns true if this dialect requires the `TABLE` keyword after `DESCRIBE`
719    ///
720    /// Defaults to false.
721    ///
722    /// If true, the following statement is valid: `DESCRIBE TABLE my_table`
723    /// If false, the following statements are valid: `DESCRIBE my_table` and `DESCRIBE table`
724    fn describe_requires_table_keyword(&self) -> bool {
725        false
726    }
727
728    /// Returns true if this dialect allows the `EXTRACT` function to words other than [`Keyword`].
729    fn allow_extract_custom(&self) -> bool {
730        false
731    }
732
733    /// Returns true if this dialect allows the `EXTRACT` function to use single quotes in the part being extracted.
734    fn allow_extract_single_quotes(&self) -> bool {
735        false
736    }
737
738    /// Returns true if this dialect allows dollar placeholders
739    /// e.g. `SELECT $var` (SQLite)
740    fn supports_dollar_placeholder(&self) -> bool {
741        false
742    }
743
744    /// Does the dialect support with clause in create index statement?
745    /// e.g. `CREATE INDEX idx ON t WITH (key = value, key2)`
746    fn supports_create_index_with_clause(&self) -> bool {
747        false
748    }
749
750    /// Whether `INTERVAL` expressions require units (called "qualifiers" in the ANSI SQL spec) to be specified,
751    /// e.g. `INTERVAL 1 DAY` vs `INTERVAL 1`.
752    ///
753    /// Expressions within intervals (e.g. `INTERVAL '1' + '1' DAY`) are only allowed when units are required.
754    ///
755    /// See <https://github.com/sqlparser-rs/sqlparser-rs/pull/1398> for more information.
756    ///
757    /// When `true`:
758    /// * `INTERVAL '1' DAY` is VALID
759    /// * `INTERVAL 1 + 1 DAY` is VALID
760    /// * `INTERVAL '1' + '1' DAY` is VALID
761    /// * `INTERVAL '1'` is INVALID
762    ///
763    /// When `false`:
764    /// * `INTERVAL '1'` is VALID
765    /// * `INTERVAL '1' DAY` is VALID — unit is not required, but still allowed
766    /// * `INTERVAL 1 + 1 DAY` is INVALID
767    fn require_interval_qualifier(&self) -> bool {
768        false
769    }
770
771    fn supports_explain_with_utility_options(&self) -> bool {
772        false
773    }
774
775    fn supports_asc_desc_in_column_definition(&self) -> bool {
776        false
777    }
778
779    /// Returns true if the dialect supports `a!` expressions
780    fn supports_factorial_operator(&self) -> bool {
781        false
782    }
783
784    /// Returns true if the dialect supports nested comments
785    /// e.g. `/* /* nested */ */`
786    fn supports_nested_comments(&self) -> bool {
787        false
788    }
789
790    /// Returns true if this dialect supports treating the equals operator `=` within a `SelectItem`
791    /// as an alias assignment operator, rather than a boolean expression.
792    /// For example: the following statements are equivalent for such a dialect:
793    /// ```sql
794    ///  SELECT col_alias = col FROM tbl;
795    ///  SELECT col_alias AS col FROM tbl;
796    /// ```
797    fn supports_eq_alias_assignment(&self) -> bool {
798        false
799    }
800
801    /// Returns true if this dialect supports the `TRY_CONVERT` function
802    fn supports_try_convert(&self) -> bool {
803        false
804    }
805
806    /// Returns true if the dialect supports `!a` syntax for boolean `NOT` expressions.
807    fn supports_bang_not_operator(&self) -> bool {
808        false
809    }
810
811    /// Returns true if the dialect supports the `LISTEN`, `UNLISTEN` and `NOTIFY` statements
812    fn supports_listen_notify(&self) -> bool {
813        false
814    }
815
816    /// Returns true if the dialect supports the `LOAD DATA` statement
817    fn supports_load_data(&self) -> bool {
818        false
819    }
820
821    /// Returns true if the dialect supports the `LOAD extension` statement
822    fn supports_load_extension(&self) -> bool {
823        false
824    }
825
826    /// Returns true if this dialect expects the `TOP` option
827    /// before the `ALL`/`DISTINCT` options in a `SELECT` statement.
828    fn supports_top_before_distinct(&self) -> bool {
829        false
830    }
831
832    /// Returns true if the dialect supports boolean literals (`true` and `false`).
833    /// For example, in MSSQL these are treated as identifiers rather than boolean literals.
834    fn supports_boolean_literals(&self) -> bool {
835        true
836    }
837
838    /// Returns true if this dialect supports the `LIKE 'pattern'` option in
839    /// a `SHOW` statement before the `IN` option
840    fn supports_show_like_before_in(&self) -> bool {
841        false
842    }
843
844    /// Returns true if this dialect supports the `COMMENT` statement
845    fn supports_comment_on(&self) -> bool {
846        false
847    }
848
849    /// Returns true if the dialect supports the `CREATE TABLE SELECT` statement
850    fn supports_create_table_select(&self) -> bool {
851        false
852    }
853
854    /// Returns true if the dialect supports PartiQL for querying semi-structured data
855    /// <https://partiql.org/index.html>
856    fn supports_partiql(&self) -> bool {
857        false
858    }
859
860    /// Returns true if the specified keyword is reserved and cannot be
861    /// used as an identifier without special handling like quoting.
862    fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
863        keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
864    }
865
866    /// Returns reserved keywords when looking to parse a `TableFactor`.
867    /// See [Self::supports_from_trailing_commas]
868    fn get_reserved_keywords_for_table_factor(&self) -> &[Keyword] {
869        keywords::RESERVED_FOR_TABLE_FACTOR
870    }
871
872    /// Returns true if this dialect supports the `TABLESAMPLE` option
873    /// before the table alias option. For example:
874    ///
875    /// Table sample before alias: `SELECT * FROM tbl AS t TABLESAMPLE (10)`
876    /// Table sample after alias: `SELECT * FROM tbl TABLESAMPLE (10) AS t`
877    ///
878    /// <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#_7_6_table_reference>
879    fn supports_table_sample_before_alias(&self) -> bool {
880        false
881    }
882
883    /// Returns true if this dialect supports the `INSERT INTO ... SET col1 = 1, ...` syntax.
884    ///
885    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/insert.html>
886    fn supports_insert_set(&self) -> bool {
887        false
888    }
889
890    /// Does the dialect support table function in insertion?
891    fn supports_insert_table_function(&self) -> bool {
892        false
893    }
894
895    /// Does the dialect support insert formats, e.g. `INSERT INTO ... FORMAT <format>`
896    fn supports_insert_format(&self) -> bool {
897        false
898    }
899
900    /// Returns true if this dialect supports `SET` statements without an explicit
901    /// assignment operator such as `=`. For example: `SET SHOWPLAN_XML ON`.
902    fn supports_set_stmt_without_operator(&self) -> bool {
903        false
904    }
905
906    /// Returns true if the specified keyword should be parsed as a column identifier.
907    /// See [keywords::RESERVED_FOR_COLUMN_ALIAS]
908    fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
909        !keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw)
910    }
911
912    /// Returns true if the specified keyword should be parsed as a select item alias.
913    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
914    /// to enable looking ahead if needed.
915    fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
916        explicit || self.is_column_alias(kw, parser)
917    }
918
919    /// Returns true if the specified keyword should be parsed as a table factor alias.
920    /// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
921    /// to enable looking ahead if needed.
922    fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
923        explicit || !keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
924    }
925
926    /// Returns true if this dialect supports querying historical table data
927    /// by specifying which version of the data to query.
928    fn supports_timestamp_versioning(&self) -> bool {
929        false
930    }
931
932    /// Returns true if this dialect supports the E'...' syntax for string literals
933    ///
934    /// Postgres: <https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE>
935    fn supports_string_escape_constant(&self) -> bool {
936        false
937    }
938
939    /// Returns true if the dialect supports the table hints in the `FROM` clause.
940    fn supports_table_hints(&self) -> bool {
941        false
942    }
943
944    /// Returns true if this dialect requires a whitespace character after `--` to start a single line comment.
945    ///
946    /// MySQL: <https://dev.mysql.com/doc/refman/8.4/en/ansi-diff-comments.html>
947    /// e.g. UPDATE account SET balance=balance--1
948    //       WHERE account_id=5752             ^^^ will be interpreted as two minus signs instead of a comment
949    fn requires_single_line_comment_whitespace(&self) -> bool {
950        false
951    }
952
953    /// Returns true if the dialect supports array type definition with brackets with
954    /// an optional size. For example:
955    /// ```CREATE TABLE my_table (arr1 INT[], arr2 INT[3])```
956    /// ```SELECT x::INT[]```
957    fn supports_array_typedef_with_brackets(&self) -> bool {
958        false
959    }
960    /// Returns true if the dialect supports geometric types.
961    ///
962    /// Postgres: <https://www.postgresql.org/docs/9.5/functions-geometry.html>
963    /// e.g. @@ circle '((0,0),10)'
964    fn supports_geometric_types(&self) -> bool {
965        false
966    }
967
968    /// Returns true if the dialect supports `ORDER BY ALL`.
969    /// `ALL` which means all columns of the SELECT clause.
970    ///
971    /// For example: ```SELECT * FROM addresses ORDER BY ALL;```.
972    fn supports_order_by_all(&self) -> bool {
973        false
974    }
975}
976
977/// This represents the operators for which precedence must be defined
978///
979/// higher number -> higher precedence
980#[derive(Debug, Clone, Copy)]
981pub enum Precedence {
982    Period,
983    DoubleColon,
984    AtTz,
985    MulDivModOp,
986    PlusMinus,
987    Xor,
988    Ampersand,
989    Caret,
990    Pipe,
991    Between,
992    Eq,
993    Like,
994    Is,
995    PgOther,
996    UnaryNot,
997    And,
998    Or,
999}
1000
1001impl dyn Dialect {
1002    #[inline]
1003    pub fn is<T: Dialect>(&self) -> bool {
1004        // borrowed from `Any` implementation
1005        TypeId::of::<T>() == self.dialect()
1006    }
1007}
1008
1009/// Returns the built in [`Dialect`] corresponding to `dialect_name`.
1010///
1011/// See [`Dialect`] documentation for an example.
1012pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect>> {
1013    let dialect_name = dialect_name.as_ref();
1014    match dialect_name.to_lowercase().as_str() {
1015        "generic" => Some(Box::new(GenericDialect)),
1016        "mysql" => Some(Box::new(MySqlDialect {})),
1017        "postgresql" | "postgres" => Some(Box::new(PostgreSqlDialect {})),
1018        "hive" => Some(Box::new(HiveDialect {})),
1019        "sqlite" => Some(Box::new(SQLiteDialect {})),
1020        "snowflake" => Some(Box::new(SnowflakeDialect)),
1021        "redshift" => Some(Box::new(RedshiftSqlDialect {})),
1022        "mssql" => Some(Box::new(MsSqlDialect {})),
1023        "clickhouse" => Some(Box::new(ClickHouseDialect {})),
1024        "bigquery" => Some(Box::new(BigQueryDialect)),
1025        "ansi" => Some(Box::new(AnsiDialect {})),
1026        "duckdb" => Some(Box::new(DuckDbDialect {})),
1027        "databricks" => Some(Box::new(DatabricksDialect {})),
1028        _ => None,
1029    }
1030}
1031
1032#[cfg(test)]
1033mod tests {
1034    use super::*;
1035
1036    struct DialectHolder<'a> {
1037        dialect: &'a dyn Dialect,
1038    }
1039
1040    #[test]
1041    fn test_is_dialect() {
1042        let generic_dialect: &dyn Dialect = &GenericDialect {};
1043        let ansi_dialect: &dyn Dialect = &AnsiDialect {};
1044
1045        let generic_holder = DialectHolder {
1046            dialect: generic_dialect,
1047        };
1048        let ansi_holder = DialectHolder {
1049            dialect: ansi_dialect,
1050        };
1051
1052        assert!(dialect_of!(generic_holder is GenericDialect |  AnsiDialect),);
1053        assert!(!dialect_of!(generic_holder is  AnsiDialect));
1054        assert!(dialect_of!(ansi_holder is AnsiDialect));
1055        assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
1056        assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
1057    }
1058
1059    #[test]
1060    fn test_dialect_from_str() {
1061        assert!(parse_dialect("generic").is::<GenericDialect>());
1062        assert!(parse_dialect("mysql").is::<MySqlDialect>());
1063        assert!(parse_dialect("MySql").is::<MySqlDialect>());
1064        assert!(parse_dialect("postgresql").is::<PostgreSqlDialect>());
1065        assert!(parse_dialect("postgres").is::<PostgreSqlDialect>());
1066        assert!(parse_dialect("hive").is::<HiveDialect>());
1067        assert!(parse_dialect("sqlite").is::<SQLiteDialect>());
1068        assert!(parse_dialect("snowflake").is::<SnowflakeDialect>());
1069        assert!(parse_dialect("SnowFlake").is::<SnowflakeDialect>());
1070        assert!(parse_dialect("MsSql").is::<MsSqlDialect>());
1071        assert!(parse_dialect("clickhouse").is::<ClickHouseDialect>());
1072        assert!(parse_dialect("ClickHouse").is::<ClickHouseDialect>());
1073        assert!(parse_dialect("bigquery").is::<BigQueryDialect>());
1074        assert!(parse_dialect("BigQuery").is::<BigQueryDialect>());
1075        assert!(parse_dialect("ansi").is::<AnsiDialect>());
1076        assert!(parse_dialect("ANSI").is::<AnsiDialect>());
1077        assert!(parse_dialect("duckdb").is::<DuckDbDialect>());
1078        assert!(parse_dialect("DuckDb").is::<DuckDbDialect>());
1079        assert!(parse_dialect("DataBricks").is::<DatabricksDialect>());
1080        assert!(parse_dialect("databricks").is::<DatabricksDialect>());
1081
1082        // error cases
1083        assert!(dialect_from_str("Unknown").is_none());
1084        assert!(dialect_from_str("").is_none());
1085    }
1086
1087    fn parse_dialect(v: &str) -> Box<dyn Dialect> {
1088        dialect_from_str(v).unwrap()
1089    }
1090
1091    #[test]
1092    fn identifier_quote_style() {
1093        let tests: Vec<(&dyn Dialect, &str, Option<char>)> = vec![
1094            (&GenericDialect {}, "id", None),
1095            (&SQLiteDialect {}, "id", Some('`')),
1096            (&PostgreSqlDialect {}, "id", Some('"')),
1097        ];
1098
1099        for (dialect, ident, expected) in tests {
1100            let actual = dialect.identifier_quote_style(ident);
1101
1102            assert_eq!(actual, expected);
1103        }
1104    }
1105
1106    #[test]
1107    fn parse_with_wrapped_dialect() {
1108        /// Wrapper for a dialect. In a real-world example, this wrapper
1109        /// would tweak the behavior of the dialect. For the test case,
1110        /// it wraps all methods unaltered.
1111        #[derive(Debug)]
1112        struct WrappedDialect(MySqlDialect);
1113
1114        impl Dialect for WrappedDialect {
1115            fn dialect(&self) -> std::any::TypeId {
1116                self.0.dialect()
1117            }
1118
1119            fn is_identifier_start(&self, ch: char) -> bool {
1120                self.0.is_identifier_start(ch)
1121            }
1122
1123            fn is_delimited_identifier_start(&self, ch: char) -> bool {
1124                self.0.is_delimited_identifier_start(ch)
1125            }
1126
1127            fn is_nested_delimited_identifier_start(&self, ch: char) -> bool {
1128                self.0.is_nested_delimited_identifier_start(ch)
1129            }
1130
1131            fn peek_nested_delimited_identifier_quotes(
1132                &self,
1133                chars: std::iter::Peekable<std::str::Chars<'_>>,
1134            ) -> Option<(char, Option<char>)> {
1135                self.0.peek_nested_delimited_identifier_quotes(chars)
1136            }
1137
1138            fn identifier_quote_style(&self, identifier: &str) -> Option<char> {
1139                self.0.identifier_quote_style(identifier)
1140            }
1141
1142            fn supports_string_literal_backslash_escape(&self) -> bool {
1143                self.0.supports_string_literal_backslash_escape()
1144            }
1145
1146            fn supports_filter_during_aggregation(&self) -> bool {
1147                self.0.supports_filter_during_aggregation()
1148            }
1149
1150            fn supports_within_after_array_aggregation(&self) -> bool {
1151                self.0.supports_within_after_array_aggregation()
1152            }
1153
1154            fn supports_group_by_expr(&self) -> bool {
1155                self.0.supports_group_by_expr()
1156            }
1157
1158            fn supports_in_empty_list(&self) -> bool {
1159                self.0.supports_in_empty_list()
1160            }
1161
1162            fn convert_type_before_value(&self) -> bool {
1163                self.0.convert_type_before_value()
1164            }
1165
1166            fn parse_prefix(
1167                &self,
1168                parser: &mut sqlparser::parser::Parser,
1169            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
1170                self.0.parse_prefix(parser)
1171            }
1172
1173            fn parse_infix(
1174                &self,
1175                parser: &mut sqlparser::parser::Parser,
1176                expr: &Expr,
1177                precedence: u8,
1178            ) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
1179                self.0.parse_infix(parser, expr, precedence)
1180            }
1181
1182            fn get_next_precedence(
1183                &self,
1184                parser: &sqlparser::parser::Parser,
1185            ) -> Option<Result<u8, sqlparser::parser::ParserError>> {
1186                self.0.get_next_precedence(parser)
1187            }
1188
1189            fn parse_statement(
1190                &self,
1191                parser: &mut sqlparser::parser::Parser,
1192            ) -> Option<Result<Statement, sqlparser::parser::ParserError>> {
1193                self.0.parse_statement(parser)
1194            }
1195
1196            fn is_identifier_part(&self, ch: char) -> bool {
1197                self.0.is_identifier_part(ch)
1198            }
1199        }
1200
1201        #[allow(clippy::needless_raw_string_hashes)]
1202        let statement = r#"SELECT 'Wayne\'s World'"#;
1203        let res1 = Parser::parse_sql(&MySqlDialect {}, statement);
1204        let res2 = Parser::parse_sql(&WrappedDialect(MySqlDialect {}), statement);
1205        assert!(res1.is_ok());
1206        assert_eq!(res1, res2);
1207    }
1208}