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