@@ -35,11 +35,10 @@ use serde::{Deserialize, Serialize};
35
35
use sqlparser_derive:: { Visit , VisitMut } ;
36
36
37
37
use crate :: ast:: DollarQuotedString ;
38
+ use crate :: dialect:: Dialect ;
38
39
use crate :: dialect:: {
39
- BigQueryDialect , DuckDbDialect , GenericDialect , HiveDialect , PostgreSqlDialect ,
40
- SnowflakeDialect ,
40
+ BigQueryDialect , DuckDbDialect , GenericDialect , PostgreSqlDialect , SnowflakeDialect ,
41
41
} ;
42
- use crate :: dialect:: { Dialect , MySqlDialect } ;
43
42
use crate :: keywords:: { Keyword , ALL_KEYWORDS , ALL_KEYWORDS_INDEX } ;
44
43
45
44
/// SQL Token enumeration
@@ -821,7 +820,7 @@ impl<'a> Tokenizer<'a> {
821
820
822
821
// mysql dialect supports identifiers that start with a numeric prefix,
823
822
// as long as they aren't an exponent number.
824
- if dialect_of ! ( self is MySqlDialect | HiveDialect ) && exponent_part. is_empty ( ) {
823
+ if self . dialect . supports_numeric_prefix ( ) && exponent_part. is_empty ( ) {
825
824
let word =
826
825
peeking_take_while ( chars, |ch| self . dialect . is_identifier_part ( ch) ) ;
827
826
@@ -1544,7 +1543,10 @@ impl<'a: 'b, 'b> Unescape<'a, 'b> {
1544
1543
#[ cfg( test) ]
1545
1544
mod tests {
1546
1545
use super :: * ;
1547
- use crate :: dialect:: { BigQueryDialect , ClickHouseDialect , MsSqlDialect } ;
1546
+ use crate :: dialect:: {
1547
+ BigQueryDialect , ClickHouseDialect , HiveDialect , MsSqlDialect , MySqlDialect ,
1548
+ } ;
1549
+ use core:: fmt:: Debug ;
1548
1550
1549
1551
#[ test]
1550
1552
fn tokenizer_error_impl ( ) {
@@ -2414,6 +2416,54 @@ mod tests {
2414
2416
check_unescape ( r"Hello\xCADRust" , None ) ;
2415
2417
}
2416
2418
2419
+ #[ test]
2420
+ fn tokenize_numeric_prefix_trait ( ) {
2421
+ #[ derive( Debug ) ]
2422
+ struct NumericPrefixDialect ;
2423
+
2424
+ impl Dialect for NumericPrefixDialect {
2425
+ fn is_identifier_start ( & self , ch : char ) -> bool {
2426
+ ch. is_ascii_lowercase ( )
2427
+ || ch. is_ascii_uppercase ( )
2428
+ || ch. is_ascii_digit ( )
2429
+ || ch == '$'
2430
+ }
2431
+
2432
+ fn is_identifier_part ( & self , ch : char ) -> bool {
2433
+ ch. is_ascii_lowercase ( )
2434
+ || ch. is_ascii_uppercase ( )
2435
+ || ch. is_ascii_digit ( )
2436
+ || ch == '_'
2437
+ || ch == '$'
2438
+ || ch == '{'
2439
+ || ch == '}'
2440
+ }
2441
+
2442
+ fn supports_numeric_prefix ( & self ) -> bool {
2443
+ true
2444
+ }
2445
+ }
2446
+
2447
+ tokenize_numeric_prefix_inner ( & NumericPrefixDialect { } ) ;
2448
+ tokenize_numeric_prefix_inner ( & HiveDialect { } ) ;
2449
+ tokenize_numeric_prefix_inner ( & MySqlDialect { } ) ;
2450
+ }
2451
+
2452
+ fn tokenize_numeric_prefix_inner ( dialect : & dyn Dialect ) {
2453
+ let sql = r#"SELECT * FROM 1"# ;
2454
+ let tokens = Tokenizer :: new ( dialect, sql) . tokenize ( ) . unwrap ( ) ;
2455
+ let expected = vec ! [
2456
+ Token :: make_keyword( "SELECT" ) ,
2457
+ Token :: Whitespace ( Whitespace :: Space ) ,
2458
+ Token :: Mul ,
2459
+ Token :: Whitespace ( Whitespace :: Space ) ,
2460
+ Token :: make_keyword( "FROM" ) ,
2461
+ Token :: Whitespace ( Whitespace :: Space ) ,
2462
+ Token :: Number ( String :: from( "1" ) , false ) ,
2463
+ ] ;
2464
+ compare ( expected, tokens) ;
2465
+ }
2466
+
2417
2467
#[ test]
2418
2468
fn tokenize_quoted_string_escape ( ) {
2419
2469
for ( sql, expected, expected_unescaped) in [
0 commit comments