@@ -19,6 +19,8 @@ mod test_utils;
1919
2020use test_utils:: * ;
2121
22+ use sqlparser:: ast:: Expr ;
23+ use sqlparser:: ast:: Value ;
2224use sqlparser:: ast:: * ;
2325use sqlparser:: dialect:: { GenericDialect , MySqlDialect } ;
2426use sqlparser:: tokenizer:: Token ;
@@ -176,6 +178,50 @@ fn parse_quote_identifiers() {
176178 }
177179}
178180
181+ #[ test]
182+ fn parse_unterminated_escape ( ) {
183+ let sql = r#"SELECT 'I\'m not fine\'"# ;
184+ let result = std:: panic:: catch_unwind ( || mysql ( ) . one_statement_parses_to ( sql, "" ) ) ;
185+ assert ! ( result. is_err( ) ) ;
186+
187+ let sql = r#"SELECT 'I\\'m not fine'"# ;
188+ let result = std:: panic:: catch_unwind ( || mysql ( ) . one_statement_parses_to ( sql, "" ) ) ;
189+ assert ! ( result. is_err( ) ) ;
190+ }
191+
192+ #[ test]
193+ fn parse_escaped_string ( ) {
194+ let sql = r#"SELECT 'I\'m fine'"# ;
195+
196+ let stmt = mysql ( ) . one_statement_parses_to ( sql, "" ) ;
197+
198+ match stmt {
199+ Statement :: Query ( query) => match query. body {
200+ SetExpr :: Select ( value) => {
201+ let expr = expr_from_projection ( only ( & value. projection ) ) ;
202+ assert_eq ! (
203+ * expr,
204+ Expr :: Value ( Value :: SingleQuotedString ( "I'm fine" . to_string( ) ) )
205+ ) ;
206+ }
207+ _ => unreachable ! ( ) ,
208+ } ,
209+ _ => unreachable ! ( ) ,
210+ } ;
211+
212+ let sql = r#"SELECT 'I''m fine'"# ;
213+
214+ let projection = mysql ( ) . verified_only_select ( sql) . projection ;
215+ let item = projection. get ( 0 ) . unwrap ( ) ;
216+
217+ match & item {
218+ SelectItem :: UnnamedExpr ( Expr :: Value ( value) ) => {
219+ assert_eq ! ( * value, Value :: SingleQuotedString ( "I'm fine" . to_string( ) ) ) ;
220+ }
221+ _ => unreachable ! ( ) ,
222+ }
223+ }
224+
179225#[ test]
180226fn parse_create_table_with_minimum_display_width ( ) {
181227 let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3), bar_smallint SMALLINT(5), bar_int INT(11), bar_bigint BIGINT(20))" ;
0 commit comments