2424 * Portions Copyright (c) 1994, Regents of the University of California
2525 *
2626 * IDENTIFICATION
27- * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.130 2006/03/05 15:58:34 momjian Exp $
27+ * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.131 2006/03/06 19:49:20 momjian Exp $
2828 *
2929 *-------------------------------------------------------------------------
3030 */
@@ -51,13 +51,14 @@ static int xcdepth = 0; /* depth of nesting in slash-star comments */
5151static char *dolqstart; /* current $foo$ quote start string */
5252
5353/*
54- * GUC variable . This is a DIRECT violation of the warning given at the
54+ * GUC variables . This is a DIRECT violation of the warning given at the
5555 * head of gram.y, ie flex/bison code must not depend on any GUC variables;
5656 * as such, changing its value can induce very unintuitive behavior.
5757 * But we shall have to live with it as a short-term thing until the switch
5858 * to SQL-standard string syntax is complete.
5959 */
6060bool escape_string_warning;
61+ bool standard_conforming_strings;
6162
6263static bool warn_on_first_escape;
6364
@@ -77,6 +78,7 @@ static void addlitchar(unsigned char ychar);
7778static char *litbufdup (void );
7879static int pg_err_position (void );
7980static void check_escape_warning (void );
81+ static void check_string_escape_warning (unsigned char ychar);
8082
8183/*
8284 * When we parse a token that requires multiple lexer rules to process,
@@ -119,14 +121,16 @@ static unsigned char unescape_single_char(unsigned char c);
119121 * <xc> extended C-style comments
120122 * <xd> delimited identifiers (double-quoted identifiers)
121123 * <xh> hexadecimal numeric string
122- * <xq> quoted strings
124+ * <xq> standard quoted strings
125+ * <xe> extended quoted strings (support backslash escape sequences)
123126 * <xdolq> $foo$ quoted strings
124127 */
125128
126129%x xb
127130%x xc
128131%x xd
129132%x xh
133+ %x xe
130134%x xq
131135%x xdolq
132136
@@ -200,16 +204,18 @@ xnstart [nN]{quote}
200204
201205/* Quoted string that allows backslash escapes */
202206xestart [eE ]{quote }
207+ xeinside [^ \\ ' ]+
208+ xeescape [\\ ][^ 0 -7 ]
209+ xeoctesc [\\ ][0 -7 ]{1,3 }
210+ xehexesc [\\ ]x[0 -9A -Fa -f ]{1,2 }
203211
204212/* Extended quote
205213 * xqdouble implements embedded quote, ''''
206214 */
207215xqstart {quote }
208216xqdouble {quote }{quote }
209217xqinside [^ \\ ' ]+
210- xqescape [\\ ][^ 0 -7 ]
211- xqoctesc [\\ ][0 -7 ]{1,3 }
212- xqhexesc [\\ ]x[0 -9A -Fa -f ]{1,2 }
218+ xqbackslash [\\ ]
213219
214220/* $foo$ style quotes ("dollar quoting")
215221 * The quoted string starts with $foo$ where "foo" is an optional string
@@ -428,73 +434,62 @@ other .
428434{xqstart } {
429435 warn_on_first_escape = true ;
430436 token_start = yytext;
431- BEGIN (xq);
437+ if (standard_conforming_strings)
438+ BEGIN (xq);
439+ else
440+ BEGIN (xe);
432441 startlit ();
433442 }
434443{xestart } {
435444 warn_on_first_escape = false ;
436445 token_start = yytext;
437- BEGIN (xq );
446+ BEGIN (xe );
438447 startlit ();
439448 }
440- <xq >{quotestop } |
441- <xq >{quotefail } {
449+ <xq , xe >{quotestop } |
450+ <xq , xe >{quotefail } {
442451 yyless (1 );
443452 BEGIN (INITIAL);
444453 yylval.str = litbufdup ();
445454 return SCONST;
446455 }
447- <xq >{xqdouble } {
456+ <xq , xe >{xqdouble } {
448457 addlitchar (' \' ' );
449458 }
450459<xq >{xqinside } {
451460 addlit (yytext, yyleng);
452461 }
453- <xq >{xqescape } {
454- if (yytext[1 ] == ' \' ' )
455- {
456- if (warn_on_first_escape && escape_string_warning)
457- ereport (WARNING,
458- (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
459- errmsg (" nonstandard use of \\ ' in a string literal" ),
460- errhint (" Use '' to write quotes in strings, or use the escape string syntax (E'...')." ),
461- errposition (pg_err_position ())));
462- warn_on_first_escape = false ; /* warn only once per string */
463- }
464- else if (yytext[1 ] == ' \\ ' )
465- {
466- if (warn_on_first_escape && escape_string_warning)
467- ereport (WARNING,
468- (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
469- errmsg (" nonstandard use of \\\\ in a string literal" ),
470- errhint (" Use the escape string syntax for backslashes, e.g., E'\\\\ '." ),
471- errposition (pg_err_position ())));
472- warn_on_first_escape = false ; /* warn only once per string */
473- }
474- else
475- check_escape_warning ();
462+ <xe >{xeinside } {
463+ addlit (yytext, yyleng);
464+ }
465+ <xq >{xqbackslash } {
466+ check_string_escape_warning (yytext[1 ]);
467+ addlitchar (' \\ ' );
468+ }
469+ <xe >{xeescape } {
470+ check_string_escape_warning (yytext[1 ]);
476471 addlitchar (unescape_single_char (yytext[1 ]));
477472 }
478- <xq >{ xqoctesc } {
473+ <xe >{ xeoctesc } {
479474 unsigned char c = strtoul (yytext+1 , NULL , 8 );
480475
481476 check_escape_warning ();
482477 addlitchar (c);
483478 }
484- <xq >{ xqhexesc } {
479+ <xe >{ xehexesc } {
485480 unsigned char c = strtoul (yytext+2 , NULL , 16 );
486481
487482 check_escape_warning ();
488483 addlitchar (c);
489484 }
490- <xq >{quotecontinue } {
485+ <xq , xe >{quotecontinue } {
491486 /* ignore */
492487 }
493- <xq >. {
488+ <xe >. {
494489 /* This is only needed for \ just before EOF */
495490 addlitchar (yytext[0 ]);
496491 }
497- <xq ><<EOF>> { yyerror (" unterminated quoted string" ); }
492+ <xq , xe ><<EOF>> { yyerror (" unterminated quoted string" ); }
498493
499494{dolqdelim } {
500495 token_start = yytext;
@@ -875,6 +870,33 @@ unescape_single_char(unsigned char c)
875870 }
876871}
877872
873+ static void
874+ check_string_escape_warning (unsigned char ychar)
875+ {
876+ if (ychar == ' \' ' )
877+ {
878+ if (warn_on_first_escape && escape_string_warning)
879+ ereport (WARNING,
880+ (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
881+ errmsg (" nonstandard use of \\ ' in a string literal" ),
882+ errhint (" Use '' to write quotes in strings, or use the escape string syntax (E'...')." ),
883+ errposition (pg_err_position ())));
884+ warn_on_first_escape = false ; /* warn only once per string */
885+ }
886+ else if (ychar == ' \\ ' )
887+ {
888+ if (warn_on_first_escape && escape_string_warning)
889+ ereport (WARNING,
890+ (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
891+ errmsg (" nonstandard use of \\\\ in a string literal" ),
892+ errhint (" Use the escape string syntax for backslashes, e.g., E'\\\\ '." ),
893+ errposition (pg_err_position ())));
894+ warn_on_first_escape = false ; /* warn only once per string */
895+ }
896+ else
897+ check_escape_warning ();
898+ }
899+
878900static void
879901check_escape_warning (void )
880902{
0 commit comments