Thanks to visit codestin.com
Credit goes to docs.rs

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