@@ -89,6 +89,15 @@ macro_rules! dialect_of {
8989///
9090/// [module level documentation]: crate
9191pub trait Dialect : Debug + Any {
92+ /// Determine the [`TypeId`] of this dialect.
93+ ///
94+ /// By default, return the same [`TypeId`] as [`Any::type_id`]. Can be overriden
95+ /// by dialects that behave like other dialects
96+ /// (for example when wrapping a dialect).
97+ fn dialect ( & self ) -> TypeId {
98+ self . type_id ( )
99+ }
100+
92101 /// Determine if a character starts a quoted identifier. The default
93102 /// implementation, accepting "double quoted" ids is both ANSI-compliant
94103 /// and appropriate for most dialects (with the notable exception of
@@ -164,7 +173,7 @@ impl dyn Dialect {
164173 #[ inline]
165174 pub fn is < T : Dialect > ( & self ) -> bool {
166175 // borrowed from `Any` implementation
167- TypeId :: of :: < T > ( ) == self . type_id ( )
176+ TypeId :: of :: < T > ( ) == self . dialect ( )
168177 }
169178}
170179
@@ -248,4 +257,98 @@ mod tests {
248257 fn parse_dialect ( v : & str ) -> Box < dyn Dialect > {
249258 dialect_from_str ( v) . unwrap ( )
250259 }
260+
261+ #[ test]
262+ fn parse_with_wrapped_dialect ( ) {
263+ /// Wrapper for a dialect. In a real-world example, this wrapper
264+ /// would tweak the behavior of the dialect. For the test case,
265+ /// it wraps all methods unaltered.
266+ #[ derive( Debug ) ]
267+ struct WrappedDialect ( MySqlDialect ) ;
268+
269+ impl Dialect for WrappedDialect {
270+ fn dialect ( & self ) -> std:: any:: TypeId {
271+ self . 0 . dialect ( )
272+ }
273+
274+ fn is_identifier_start ( & self , ch : char ) -> bool {
275+ self . 0 . is_identifier_start ( ch)
276+ }
277+
278+ fn is_delimited_identifier_start ( & self , ch : char ) -> bool {
279+ self . 0 . is_delimited_identifier_start ( ch)
280+ }
281+
282+ fn is_proper_identifier_inside_quotes (
283+ & self ,
284+ chars : std:: iter:: Peekable < std:: str:: Chars < ' _ > > ,
285+ ) -> bool {
286+ self . 0 . is_proper_identifier_inside_quotes ( chars)
287+ }
288+
289+ fn supports_filter_during_aggregation ( & self ) -> bool {
290+ self . 0 . supports_filter_during_aggregation ( )
291+ }
292+
293+ fn supports_within_after_array_aggregation ( & self ) -> bool {
294+ self . 0 . supports_within_after_array_aggregation ( )
295+ }
296+
297+ fn supports_group_by_expr ( & self ) -> bool {
298+ self . 0 . supports_group_by_expr ( )
299+ }
300+
301+ fn supports_substring_from_for_expr ( & self ) -> bool {
302+ self . 0 . supports_substring_from_for_expr ( )
303+ }
304+
305+ fn supports_in_empty_list ( & self ) -> bool {
306+ self . 0 . supports_in_empty_list ( )
307+ }
308+
309+ fn convert_type_before_value ( & self ) -> bool {
310+ self . 0 . convert_type_before_value ( )
311+ }
312+
313+ fn parse_prefix (
314+ & self ,
315+ parser : & mut sqlparser:: parser:: Parser ,
316+ ) -> Option < Result < Expr , sqlparser:: parser:: ParserError > > {
317+ self . 0 . parse_prefix ( parser)
318+ }
319+
320+ fn parse_infix (
321+ & self ,
322+ parser : & mut sqlparser:: parser:: Parser ,
323+ expr : & Expr ,
324+ precedence : u8 ,
325+ ) -> Option < Result < Expr , sqlparser:: parser:: ParserError > > {
326+ self . 0 . parse_infix ( parser, expr, precedence)
327+ }
328+
329+ fn get_next_precedence (
330+ & self ,
331+ parser : & sqlparser:: parser:: Parser ,
332+ ) -> Option < Result < u8 , sqlparser:: parser:: ParserError > > {
333+ self . 0 . get_next_precedence ( parser)
334+ }
335+
336+ fn parse_statement (
337+ & self ,
338+ parser : & mut sqlparser:: parser:: Parser ,
339+ ) -> Option < Result < Statement , sqlparser:: parser:: ParserError > > {
340+ self . 0 . parse_statement ( parser)
341+ }
342+
343+ fn is_identifier_part ( & self , ch : char ) -> bool {
344+ self . 0 . is_identifier_part ( ch)
345+ }
346+ }
347+
348+ let statement = r#"SELECT 'Wayne\'s World'"# ;
349+ let res1 = Parser :: parse_sql ( & MySqlDialect { } , statement) ;
350+ let res2 = Parser :: parse_sql ( & WrappedDialect ( MySqlDialect { } ) , statement) ;
351+ assert ! ( res1. is_ok( ) ) ;
352+ assert_eq ! ( res1, res2) ;
353+ }
251354}
0 commit comments