1mod ansi;
14mod bigquery;
15mod clickhouse;
16mod generic;
17mod hive;
18mod mssql;
19mod mysql;
20mod postgresql;
21mod redshift;
22mod snowflake;
23mod sqlite;
24
25use crate::ast::{Expr, Statement};
26use core::any::{Any, TypeId};
27use core::fmt::Debug;
28use core::iter::Peekable;
29use core::str::Chars;
30
31pub use self::ansi::AnsiDialect;
32pub use self::bigquery::BigQueryDialect;
33pub use self::clickhouse::ClickHouseDialect;
34pub use self::generic::GenericDialect;
35pub use self::hive::HiveDialect;
36pub use self::mssql::MsSqlDialect;
37pub use self::mysql::MySqlDialect;
38pub use self::postgresql::PostgreSqlDialect;
39pub use self::redshift::RedshiftSqlDialect;
40pub use self::snowflake::SnowflakeDialect;
41pub use self::sqlite::SQLiteDialect;
42pub use crate::keywords;
43use crate::parser::{Parser, ParserError};
44
45macro_rules! dialect_of {
48 ( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
49 ($($parsed_dialect.dialect.is::<$dialect_type>())||+)
50 };
51}
52
53pub trait Dialect: Debug + Any {
54 fn is_delimited_identifier_start(&self, ch: char) -> bool {
60 ch == '"'
61 }
62 fn is_proper_identifier_inside_quotes(&self, mut _chars: Peekable<Chars<'_>>) -> bool {
64 true
65 }
66 fn is_identifier_start(&self, ch: char) -> bool;
68 fn is_identifier_part(&self, ch: char) -> bool;
70 fn supports_filter_during_aggregation(&self) -> bool {
72 false
73 }
74 fn supports_within_after_array_aggregation(&self) -> bool {
79 false
80 }
81 fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
83 None
85 }
86 fn parse_infix(
88 &self,
89 _parser: &mut Parser,
90 _expr: &Expr,
91 _precedence: u8,
92 ) -> Option<Result<Expr, ParserError>> {
93 None
95 }
96 fn get_next_precedence(&self, _parser: &Parser) -> Option<Result<u8, ParserError>> {
98 None
100 }
101 fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
103 None
105 }
106}
107
108impl dyn Dialect {
109 #[inline]
110 pub fn is<T: Dialect>(&self) -> bool {
111 TypeId::of::<T>() == self.type_id()
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::ansi::AnsiDialect;
119 use super::generic::GenericDialect;
120 use super::*;
121
122 struct DialectHolder<'a> {
123 dialect: &'a dyn Dialect,
124 }
125
126 #[test]
127 fn test_is_dialect() {
128 let generic_dialect: &dyn Dialect = &GenericDialect {};
129 let ansi_dialect: &dyn Dialect = &AnsiDialect {};
130
131 let generic_holder = DialectHolder {
132 dialect: generic_dialect,
133 };
134 let ansi_holder = DialectHolder {
135 dialect: ansi_dialect,
136 };
137
138 assert!(dialect_of!(generic_holder is GenericDialect | AnsiDialect),);
139 assert!(!dialect_of!(generic_holder is AnsiDialect));
140 assert!(dialect_of!(ansi_holder is AnsiDialect));
141 assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
142 assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
143 }
144}