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}