sqlparser/dialect/
mod.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13mod ansi;
14mod bigquery;
15mod clickhouse;
16mod duckdb;
17mod generic;
18mod hive;
19mod mssql;
20mod mysql;
21mod postgresql;
22mod redshift;
23mod snowflake;
24mod sqlite;
25
26use crate::ast::{Expr, Statement};
27use core::any::{Any, TypeId};
28use core::fmt::Debug;
29use core::iter::Peekable;
30use core::str::Chars;
31
32pub use self::ansi::AnsiDialect;
33pub use self::bigquery::BigQueryDialect;
34pub use self::clickhouse::ClickHouseDialect;
35pub use self::duckdb::DuckDbDialect;
36pub use self::generic::GenericDialect;
37pub use self::hive::HiveDialect;
38pub use self::mssql::MsSqlDialect;
39pub use self::mysql::MySqlDialect;
40pub use self::postgresql::PostgreSqlDialect;
41pub use self::redshift::RedshiftSqlDialect;
42pub use self::snowflake::SnowflakeDialect;
43pub use self::sqlite::SQLiteDialect;
44pub use crate::keywords;
45use crate::parser::{Parser, ParserError};
46
47#[cfg(not(feature = "std"))]
48use alloc::boxed::Box;
49
50/// Convenience check if a [`Parser`] uses a certain dialect.
51///
52/// `dialect_of!(parser Is SQLiteDialect |  GenericDialect)` evaluates
53/// to `true` if `parser.dialect` is one of the [`Dialect`]s specified.
54macro_rules! dialect_of {
55    ( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
56        ($($parsed_dialect.dialect.is::<$dialect_type>())||+)
57    };
58}
59
60/// Encapsulates the differences between SQL implementations.
61///
62/// # SQL Dialects
63/// SQL implementations deviatiate from one another, either due to
64/// custom extensions or various historical reasons. This trait
65/// encapsulates the parsing differences between dialects.
66///
67/// [`GenericDialect`] is the most permissive dialect, and parses the union of
68/// all the other dialects, when there is no ambiguity.
69///
70/// # Examples
71/// Most users create a [`Dialect`] directly, as shown on the [module
72/// level documentation]:
73///
74/// ```
75/// # use sqlparser::dialect::AnsiDialect;
76/// let dialect = AnsiDialect {};
77/// ```
78///
79/// It is also possible to dynamically create a [`Dialect`] from its
80/// name. For example:
81///
82/// ```
83/// # use sqlparser::dialect::{AnsiDialect, dialect_from_str};
84/// let dialect = dialect_from_str("ansi").unwrap();
85///
86/// // Parsed dialect is an instance of `AnsiDialect`:
87/// assert!(dialect.is::<AnsiDialect>());
88/// ```
89///
90/// [module level documentation]: crate
91pub trait Dialect: Debug + Any {
92    /// Determine if a character starts a quoted identifier. The default
93    /// implementation, accepting "double quoted" ids is both ANSI-compliant
94    /// and appropriate for most dialects (with the notable exception of
95    /// MySQL, MS SQL, and sqlite). You can accept one of characters listed
96    /// in `Word::matching_end_quote` here
97    fn is_delimited_identifier_start(&self, ch: char) -> bool {
98        ch == '"' || ch == '`'
99    }
100    /// Determine if quoted characters are proper for identifier
101    fn is_proper_identifier_inside_quotes(&self, mut _chars: Peekable<Chars<'_>>) -> bool {
102        true
103    }
104    /// Determine if a character is a valid start character for an unquoted identifier
105    fn is_identifier_start(&self, ch: char) -> bool;
106    /// Determine if a character is a valid unquoted identifier character
107    fn is_identifier_part(&self, ch: char) -> bool;
108    /// Does the dialect support `FILTER (WHERE expr)` for aggregate queries?
109    fn supports_filter_during_aggregation(&self) -> bool {
110        false
111    }
112    /// Returns true if the dialect supports `ARRAY_AGG() [WITHIN GROUP (ORDER BY)]` expressions.
113    /// Otherwise, the dialect should expect an `ORDER BY` without the `WITHIN GROUP` clause, e.g. [`ANSI`]
114    ///
115    /// [`ANSI`]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#array-aggregate-function
116    fn supports_within_after_array_aggregation(&self) -> bool {
117        false
118    }
119    /// Returns true if the dialects supports `group sets, roll up, or cube` expressions.
120    fn supports_group_by_expr(&self) -> bool {
121        false
122    }
123    /// Returns true if the dialect supports `SUBSTRING(expr [FROM start] [FOR len])` expressions
124    fn supports_substring_from_for_expr(&self) -> bool {
125        true
126    }
127    /// Returns true if the dialect supports `(NOT) IN ()` expressions
128    fn supports_in_empty_list(&self) -> bool {
129        false
130    }
131    /// Dialect-specific prefix parser override
132    fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
133        // return None to fall back to the default behavior
134        None
135    }
136    /// Dialect-specific infix parser override
137    fn parse_infix(
138        &self,
139        _parser: &mut Parser,
140        _expr: &Expr,
141        _precedence: u8,
142    ) -> Option<Result<Expr, ParserError>> {
143        // return None to fall back to the default behavior
144        None
145    }
146    /// Dialect-specific precedence override
147    fn get_next_precedence(&self, _parser: &Parser) -> Option<Result<u8, ParserError>> {
148        // return None to fall back to the default behavior
149        None
150    }
151    /// Dialect-specific statement parser override
152    fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
153        // return None to fall back to the default behavior
154        None
155    }
156}
157
158impl dyn Dialect {
159    #[inline]
160    pub fn is<T: Dialect>(&self) -> bool {
161        // borrowed from `Any` implementation
162        TypeId::of::<T>() == self.type_id()
163    }
164}
165
166/// Returns the built in [`Dialect`] corresponding to `dialect_name`.
167///
168/// See [`Dialect`] documentation for an example.
169pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect>> {
170    let dialect_name = dialect_name.as_ref();
171    match dialect_name.to_lowercase().as_str() {
172        "generic" => Some(Box::new(GenericDialect)),
173        "mysql" => Some(Box::new(MySqlDialect {})),
174        "postgresql" | "postgres" => Some(Box::new(PostgreSqlDialect {})),
175        "hive" => Some(Box::new(HiveDialect {})),
176        "sqlite" => Some(Box::new(SQLiteDialect {})),
177        "snowflake" => Some(Box::new(SnowflakeDialect)),
178        "redshift" => Some(Box::new(RedshiftSqlDialect {})),
179        "mssql" => Some(Box::new(MsSqlDialect {})),
180        "clickhouse" => Some(Box::new(ClickHouseDialect {})),
181        "bigquery" => Some(Box::new(BigQueryDialect)),
182        "ansi" => Some(Box::new(AnsiDialect {})),
183        "duckdb" => Some(Box::new(DuckDbDialect {})),
184        _ => None,
185    }
186}
187
188#[cfg(test)]
189mod tests {
190    use super::ansi::AnsiDialect;
191    use super::generic::GenericDialect;
192    use super::*;
193
194    struct DialectHolder<'a> {
195        dialect: &'a dyn Dialect,
196    }
197
198    #[test]
199    fn test_is_dialect() {
200        let generic_dialect: &dyn Dialect = &GenericDialect {};
201        let ansi_dialect: &dyn Dialect = &AnsiDialect {};
202
203        let generic_holder = DialectHolder {
204            dialect: generic_dialect,
205        };
206        let ansi_holder = DialectHolder {
207            dialect: ansi_dialect,
208        };
209
210        assert!(dialect_of!(generic_holder is GenericDialect |  AnsiDialect),);
211        assert!(!dialect_of!(generic_holder is  AnsiDialect));
212        assert!(dialect_of!(ansi_holder is AnsiDialect));
213        assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
214        assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
215    }
216
217    #[test]
218    fn test_dialect_from_str() {
219        assert!(parse_dialect("generic").is::<GenericDialect>());
220        assert!(parse_dialect("mysql").is::<MySqlDialect>());
221        assert!(parse_dialect("MySql").is::<MySqlDialect>());
222        assert!(parse_dialect("postgresql").is::<PostgreSqlDialect>());
223        assert!(parse_dialect("postgres").is::<PostgreSqlDialect>());
224        assert!(parse_dialect("hive").is::<HiveDialect>());
225        assert!(parse_dialect("sqlite").is::<SQLiteDialect>());
226        assert!(parse_dialect("snowflake").is::<SnowflakeDialect>());
227        assert!(parse_dialect("SnowFlake").is::<SnowflakeDialect>());
228        assert!(parse_dialect("MsSql").is::<MsSqlDialect>());
229        assert!(parse_dialect("clickhouse").is::<ClickHouseDialect>());
230        assert!(parse_dialect("ClickHouse").is::<ClickHouseDialect>());
231        assert!(parse_dialect("bigquery").is::<BigQueryDialect>());
232        assert!(parse_dialect("BigQuery").is::<BigQueryDialect>());
233        assert!(parse_dialect("ansi").is::<AnsiDialect>());
234        assert!(parse_dialect("ANSI").is::<AnsiDialect>());
235        assert!(parse_dialect("duckdb").is::<DuckDbDialect>());
236        assert!(parse_dialect("DuckDb").is::<DuckDbDialect>());
237
238        // error cases
239        assert!(dialect_from_str("Unknown").is_none());
240        assert!(dialect_from_str("").is_none());
241    }
242
243    fn parse_dialect(v: &str) -> Box<dyn Dialect> {
244        dialect_from_str(v).unwrap()
245    }
246}