@@ -971,7 +971,10 @@ impl<'a> Tokenizer<'a> {
971971 match chars. peek ( ) {
972972 Some ( '\'' ) => {
973973 // N'...' - a <national character string literal>
974- let s = self . tokenize_single_quoted_string ( chars, '\'' , true ) ?;
974+ let backslash_escape =
975+ self . dialect . supports_string_literal_backslash_escape ( ) ;
976+ let s =
977+ self . tokenize_single_quoted_string ( chars, '\'' , backslash_escape) ?;
975978 Ok ( Some ( Token :: NationalStringLiteral ( s) ) )
976979 }
977980 _ => {
@@ -982,7 +985,7 @@ impl<'a> Tokenizer<'a> {
982985 }
983986 }
984987 // PostgreSQL accepts "escape" string constants, which are an extension to the SQL standard.
985- x @ 'e' | x @ 'E' => {
988+ x @ 'e' | x @ 'E' if self . dialect . supports_string_escape_constant ( ) => {
986989 let starting_loc = chars. location ( ) ;
987990 chars. next ( ) ; // consume, to check the next char
988991 match chars. peek ( ) {
@@ -2155,6 +2158,7 @@ mod tests {
21552158 use crate :: dialect:: {
21562159 BigQueryDialect , ClickHouseDialect , HiveDialect , MsSqlDialect , MySqlDialect , SQLiteDialect ,
21572160 } ;
2161+ use crate :: test_utils:: all_dialects_where;
21582162 use core:: fmt:: Debug ;
21592163
21602164 #[ test]
@@ -3543,4 +3547,74 @@ mod tests {
35433547 ] ;
35443548 compare ( expected, tokens) ;
35453549 }
3550+
3551+ #[ test]
3552+ fn test_national_strings_backslash_escape_not_supported ( ) {
3553+ all_dialects_where ( |dialect| !dialect. supports_string_literal_backslash_escape ( ) )
3554+ . tokenizes_to (
3555+ "select n'''''\\ '" ,
3556+ vec ! [
3557+ Token :: make_keyword( "select" ) ,
3558+ Token :: Whitespace ( Whitespace :: Space ) ,
3559+ Token :: NationalStringLiteral ( "''\\ " . to_string( ) ) ,
3560+ ] ,
3561+ ) ;
3562+ }
3563+
3564+ #[ test]
3565+ fn test_national_strings_backslash_escape_supported ( ) {
3566+ all_dialects_where ( |dialect| dialect. supports_string_literal_backslash_escape ( ) )
3567+ . tokenizes_to (
3568+ "select n'''''\\ ''" ,
3569+ vec ! [
3570+ Token :: make_keyword( "select" ) ,
3571+ Token :: Whitespace ( Whitespace :: Space ) ,
3572+ Token :: NationalStringLiteral ( "'''" . to_string( ) ) ,
3573+ ] ,
3574+ ) ;
3575+ }
3576+
3577+ #[ test]
3578+ fn test_string_escape_constant_not_supported ( ) {
3579+ all_dialects_where ( |dialect| !dialect. supports_string_escape_constant ( ) ) . tokenizes_to (
3580+ "select e'...'" ,
3581+ vec ! [
3582+ Token :: make_keyword( "select" ) ,
3583+ Token :: Whitespace ( Whitespace :: Space ) ,
3584+ Token :: make_word( "e" , None ) ,
3585+ Token :: SingleQuotedString ( "..." . to_string( ) ) ,
3586+ ] ,
3587+ ) ;
3588+
3589+ all_dialects_where ( |dialect| !dialect. supports_string_escape_constant ( ) ) . tokenizes_to (
3590+ "select E'...'" ,
3591+ vec ! [
3592+ Token :: make_keyword( "select" ) ,
3593+ Token :: Whitespace ( Whitespace :: Space ) ,
3594+ Token :: make_word( "E" , None ) ,
3595+ Token :: SingleQuotedString ( "..." . to_string( ) ) ,
3596+ ] ,
3597+ ) ;
3598+ }
3599+
3600+ #[ test]
3601+ fn test_string_escape_constant_supported ( ) {
3602+ all_dialects_where ( |dialect| dialect. supports_string_escape_constant ( ) ) . tokenizes_to (
3603+ "select e'\\ ''" ,
3604+ vec ! [
3605+ Token :: make_keyword( "select" ) ,
3606+ Token :: Whitespace ( Whitespace :: Space ) ,
3607+ Token :: EscapedStringLiteral ( "'" . to_string( ) ) ,
3608+ ] ,
3609+ ) ;
3610+
3611+ all_dialects_where ( |dialect| dialect. supports_string_escape_constant ( ) ) . tokenizes_to (
3612+ "select E'\\ ''" ,
3613+ vec ! [
3614+ Token :: make_keyword( "select" ) ,
3615+ Token :: Whitespace ( Whitespace :: Space ) ,
3616+ Token :: EscapedStringLiteral ( "'" . to_string( ) ) ,
3617+ ] ,
3618+ ) ;
3619+ }
35463620}
0 commit comments