@@ -42,14 +42,47 @@ pub use self::sqlite::SQLiteDialect;
42
42
pub use crate :: keywords;
43
43
use crate :: parser:: { Parser , ParserError } ;
44
44
45
- /// `dialect_of!(parser is SQLiteDialect | GenericDialect)` evaluates
46
- /// to `true` if `parser.dialect` is one of the `Dialect`s specified.
45
+ #[ cfg( not( feature = "std" ) ) ]
46
+ use alloc:: boxed:: Box ;
47
+
48
+ /// Convenience check if a [`Parser`] uses a certain dialect.
49
+ ///
50
+ /// `dialect_of!(parser Is SQLiteDialect | GenericDialect)` evaluates
51
+ /// to `true` if `parser.dialect` is one of the [`Dialect`]s specified.
47
52
macro_rules! dialect_of {
48
53
( $parsed_dialect: ident is $( $dialect_type: ty) |+ ) => {
49
54
( $( $parsed_dialect. dialect. is:: <$dialect_type>( ) ) ||+)
50
55
} ;
51
56
}
52
57
58
+ /// Encapsulates the differences between SQL implementations.
59
+ ///
60
+ /// # SQL Dialects
61
+ /// SQL implementations deviatiate from one another, either due to
62
+ /// custom extensions or various historical reasons. This trait
63
+ /// encapsulates the parsing differences between dialects.
64
+ ///
65
+ /// # Examples
66
+ /// Most users create a [`Dialect`] directly, as shown on the [module
67
+ /// level documentation]:
68
+ ///
69
+ /// ```
70
+ /// # use sqlparser::dialect::AnsiDialect;
71
+ /// let dialect = AnsiDialect {};
72
+ /// ```
73
+ ///
74
+ /// It is also possible to dynamically create a [`Dialect`] from its
75
+ /// name. For example:
76
+ ///
77
+ /// ```
78
+ /// # use sqlparser::dialect::{AnsiDialect, dialect_from_str};
79
+ /// let dialect = dialect_from_str("ansi").unwrap();
80
+ ///
81
+ /// // Parsed dialect is an instance of `AnsiDialect`:
82
+ /// assert!(dialect.is::<AnsiDialect>());
83
+ /// ```
84
+ ///
85
+ /// [module level documentation]: crate
53
86
pub trait Dialect : Debug + Any {
54
87
/// Determine if a character starts a quoted identifier. The default
55
88
/// implementation, accepting "double quoted" ids is both ANSI-compliant
@@ -113,6 +146,27 @@ impl dyn Dialect {
113
146
}
114
147
}
115
148
149
+ /// Returns the built in [`Dialect`] corresponding to `dialect_name`.
150
+ ///
151
+ /// See [`Dialect`] documentation for an example.
152
+ pub fn dialect_from_str ( dialect_name : impl AsRef < str > ) -> Option < Box < dyn Dialect > > {
153
+ let dialect_name = dialect_name. as_ref ( ) ;
154
+ match dialect_name. to_lowercase ( ) . as_str ( ) {
155
+ "generic" => Some ( Box :: new ( GenericDialect ) ) ,
156
+ "mysql" => Some ( Box :: new ( MySqlDialect { } ) ) ,
157
+ "postgresql" | "postgres" => Some ( Box :: new ( PostgreSqlDialect { } ) ) ,
158
+ "hive" => Some ( Box :: new ( HiveDialect { } ) ) ,
159
+ "sqlite" => Some ( Box :: new ( SQLiteDialect { } ) ) ,
160
+ "snowflake" => Some ( Box :: new ( SnowflakeDialect ) ) ,
161
+ "redshift" => Some ( Box :: new ( RedshiftSqlDialect { } ) ) ,
162
+ "mssql" => Some ( Box :: new ( MsSqlDialect { } ) ) ,
163
+ "clickhouse" => Some ( Box :: new ( ClickHouseDialect { } ) ) ,
164
+ "bigquery" => Some ( Box :: new ( BigQueryDialect ) ) ,
165
+ "ansi" => Some ( Box :: new ( AnsiDialect { } ) ) ,
166
+ _ => None ,
167
+ }
168
+ }
169
+
116
170
#[ cfg( test) ]
117
171
mod tests {
118
172
use super :: ansi:: AnsiDialect ;
@@ -141,4 +195,32 @@ mod tests {
141
195
assert ! ( dialect_of!( ansi_holder is GenericDialect | AnsiDialect ) ) ;
142
196
assert ! ( !dialect_of!( ansi_holder is GenericDialect | MsSqlDialect ) ) ;
143
197
}
198
+
199
+ #[ test]
200
+ fn test_dialect_from_str ( ) {
201
+ assert ! ( parse_dialect( "generic" ) . is:: <GenericDialect >( ) ) ;
202
+ assert ! ( parse_dialect( "mysql" ) . is:: <MySqlDialect >( ) ) ;
203
+ assert ! ( parse_dialect( "MySql" ) . is:: <MySqlDialect >( ) ) ;
204
+ assert ! ( parse_dialect( "postgresql" ) . is:: <PostgreSqlDialect >( ) ) ;
205
+ assert ! ( parse_dialect( "postgres" ) . is:: <PostgreSqlDialect >( ) ) ;
206
+ assert ! ( parse_dialect( "hive" ) . is:: <HiveDialect >( ) ) ;
207
+ assert ! ( parse_dialect( "sqlite" ) . is:: <SQLiteDialect >( ) ) ;
208
+ assert ! ( parse_dialect( "snowflake" ) . is:: <SnowflakeDialect >( ) ) ;
209
+ assert ! ( parse_dialect( "SnowFlake" ) . is:: <SnowflakeDialect >( ) ) ;
210
+ assert ! ( parse_dialect( "MsSql" ) . is:: <MsSqlDialect >( ) ) ;
211
+ assert ! ( parse_dialect( "clickhouse" ) . is:: <ClickHouseDialect >( ) ) ;
212
+ assert ! ( parse_dialect( "ClickHouse" ) . is:: <ClickHouseDialect >( ) ) ;
213
+ assert ! ( parse_dialect( "bigquery" ) . is:: <BigQueryDialect >( ) ) ;
214
+ assert ! ( parse_dialect( "BigQuery" ) . is:: <BigQueryDialect >( ) ) ;
215
+ assert ! ( parse_dialect( "ansi" ) . is:: <AnsiDialect >( ) ) ;
216
+ assert ! ( parse_dialect( "ANSI" ) . is:: <AnsiDialect >( ) ) ;
217
+
218
+ // error cases
219
+ assert ! ( dialect_from_str( "Unknown" ) . is_none( ) ) ;
220
+ assert ! ( dialect_from_str( "" ) . is_none( ) ) ;
221
+ }
222
+
223
+ fn parse_dialect ( v : & str ) -> Box < dyn Dialect > {
224
+ dialect_from_str ( v) . unwrap ( )
225
+ }
144
226
}
0 commit comments