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