diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/parser/scan.l | 56 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 17 | ||||
-rw-r--r-- | src/bin/psql/psqlscan.l | 17 | ||||
-rw-r--r-- | src/include/utils/errcodes.h | 3 | ||||
-rw-r--r-- | src/pl/plpgsql/src/scan.l | 35 |
5 files changed, 86 insertions, 42 deletions
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 4c556a5fba2..f9b0dbdb75b 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -24,7 +24,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.126 2005/06/26 03:03:38 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.127 2005/06/26 19:16:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,10 +48,19 @@ extern YYSTYPE yylval; static int xcdepth = 0; /* depth of nesting in slash-star comments */ -static char *dolqstart; /* current $foo$ quote start string */ -static bool warn_on_first_escape; +static char *dolqstart; /* current $foo$ quote start string */ + +/* + * GUC variable. This is a DIRECT violation of the warning given at the + * head of gram.y, ie flex/bison code must not depend on any GUC variables; + * as such, changing its value can induce very unintuitive behavior. + * But we shall have to live with it as a short-term thing until the switch + * to SQL-standard string syntax is complete. + */ bool escape_string_warning; +static bool warn_on_first_escape; + /* * literalbuf is used to accumulate literal values when multiple rules * are needed to parse a single literal. Call startlit to reset buffer @@ -66,6 +75,7 @@ static int literalalloc; /* current allocated buffer size */ static void addlit(char *ytext, int yleng); static void addlitchar(unsigned char ychar); static char *litbufdup(void); +static int pg_err_position(void); static void check_escape_warning(void); /* @@ -188,9 +198,8 @@ xhinside [^']* /* National character */ xnstart [nN]{quote} -/* Quote string does not warn about escapes */ +/* Quoted string that allows backslash escapes */ xestart [eE]{quote} -xeinside [^']* /* Extended quote * xqdouble implements embedded quote, '''' @@ -446,17 +455,21 @@ other . { if (warn_on_first_escape && escape_string_warning) ereport(WARNING, - (errcode(ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER), - errmsg("Invalid use of \\' in a normal string"), - errhint("Use '' to place quotes in strings, or use the escape string syntax (E'')."))); + (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("nonstandard use of \\' in a string literal"), + errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), + errposition(pg_err_position()))); + warn_on_first_escape = false; /* warn only once per string */ } else if (yytext[1] == '\\') { if (warn_on_first_escape && escape_string_warning) ereport(WARNING, - (errcode(ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER), - errmsg("Invalid use of \\\\ in a normal string"), - errhint("Use the escape string syntax for backslashes, e.g. E'\\\\'."))); + (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("nonstandard use of \\\\ in a string literal"), + errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), + errposition(pg_err_position()))); + warn_on_first_escape = false; /* warn only once per string */ } else check_escape_warning(); @@ -707,14 +720,20 @@ other . %% -void -yyerror(const char *message) +static int +pg_err_position(void) { const char *loc = token_start ? token_start : yytext; - int cursorpos; /* in multibyte encodings, return index in characters not bytes */ - cursorpos = pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1; + return pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1; +} + +void +yyerror(const char *message) +{ + const char *loc = token_start ? token_start : yytext; + int cursorpos = pg_err_position(); if (*loc == YY_END_OF_BUFFER_CHAR) { @@ -852,8 +871,9 @@ check_escape_warning(void) { if (warn_on_first_escape && escape_string_warning) ereport(WARNING, - (errcode(ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER), - errmsg("Invalid use of escapes in an ordinary string"), - errhint("Use the escape string syntax for escapes, e.g. E'\\r\\n'."))); + (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("nonstandard use of escape in a string literal"), + errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), + errposition(pg_err_position()))); warn_on_first_escape = false; /* warn only once per string */ } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 17386049426..0ab8e742336 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.269 2005/06/26 03:03:41 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.270 2005/06/26 19:16:06 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -190,7 +190,6 @@ static int max_index_keys; static int max_identifier_length; static int block_size; static bool integer_datetimes; -static bool escape_string_syntax; static bool standard_compliant_strings; /* should be static, but commands/variable.c needs to get at it */ @@ -877,7 +876,7 @@ static struct config_bool ConfigureNamesBool[] = { {"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS, - gettext_noop("Warn about backslash escapes in ordinary, non-escape-syntax strings."), + gettext_noop("Warn about backslash escapes in ordinary string literals."), NULL }, &escape_string_warning, @@ -885,18 +884,8 @@ static struct config_bool ConfigureNamesBool[] = }, { - {"escape_string_syntax", PGC_INTERNAL, PRESET_OPTIONS, - gettext_noop("Escape string syntax (E'') is supported."), - NULL, - GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE - }, - &escape_string_syntax, - true, NULL, NULL - }, - - { {"standard_compliant_strings", PGC_INTERNAL, PRESET_OPTIONS, - gettext_noop("'' strings treat backslashes literally."), + gettext_noop("'...' strings treat backslashes literally."), NULL, GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE }, diff --git a/src/bin/psql/psqlscan.l b/src/bin/psql/psqlscan.l index a093b3703f5..f62fe6224f9 100644 --- a/src/bin/psql/psqlscan.l +++ b/src/bin/psql/psqlscan.l @@ -33,7 +33,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.14 2005/06/02 17:45:19 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.15 2005/06/26 19:16:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -235,17 +235,18 @@ quotefail {quote}{whitespace}*"-" xbstart [bB]{quote} xbinside [^']* -/* Hexadecimal number - */ +/* Hexadecimal number */ xhstart [xX]{quote} xhinside [^']* -/* National character - */ +/* National character */ xnstart [nN]{quote} +/* Quoted string that allows backslash escapes */ +xestart [eE]{quote} + /* Extended quote - * xqdouble implements embedded quote + * xqdouble implements embedded quote, '''' */ xqstart {quote} xqdouble {quote}{quote} @@ -450,6 +451,10 @@ other . BEGIN(xq); ECHO; } +{xestart} { + BEGIN(xq); + ECHO; + } <xq>{quotestop} | <xq>{quotefail} { yyless(1); diff --git a/src/include/utils/errcodes.h b/src/include/utils/errcodes.h index 646193def49..636c3f7a379 100644 --- a/src/include/utils/errcodes.h +++ b/src/include/utils/errcodes.h @@ -11,7 +11,7 @@ * * Copyright (c) 2003-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.17 2005/01/01 20:44:30 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.18 2005/06/26 19:16:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -126,6 +126,7 @@ #define ERRCODE_INVALID_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2', '0','1','9') #define ERRCODE_INVALID_ESCAPE_OCTET MAKE_SQLSTATE('2','2', '0','0','D') #define ERRCODE_INVALID_ESCAPE_SEQUENCE MAKE_SQLSTATE('2','2', '0','2','5') +#define ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2', 'P','0','6') #define ERRCODE_INVALID_INDICATOR_PARAMETER_VALUE MAKE_SQLSTATE('2','2', '0','1','0') #define ERRCODE_INVALID_LIMIT_VALUE MAKE_SQLSTATE('2','2', '0','2','0') #define ERRCODE_INVALID_PARAMETER_VALUE MAKE_SQLSTATE('2','2', '0','2','3') diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l index 680a58fc018..e69c8f17b02 100644 --- a/src/pl/plpgsql/src/scan.l +++ b/src/pl/plpgsql/src/scan.l @@ -4,7 +4,7 @@ * procedural language * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.41 2005/06/22 01:35:02 neilc Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.42 2005/06/26 19:16:07 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -291,6 +291,12 @@ dump { return O_DUMP; } start_charpos = yytext; BEGIN(IN_STRING); } +[eE]' { + /* for now, treat the same as a regular literal */ + start_lineno = plpgsql_scanner_lineno(); + start_charpos = yytext; + BEGIN(IN_STRING); + } <IN_STRING>\\. { } <IN_STRING>\\ { /* can only happen with \ at EOF */ } <IN_STRING>'' { } @@ -563,18 +569,41 @@ plpgsql_get_string_value(void) memcpy(result, yytext + dolqlen, len); result[len] = '\0'; } + else if (*yytext == 'E' || *yytext == 'e') + { + /* Token is an E'...' string */ + result = (char *) palloc(yyleng + 1); /* more than enough room */ + len = 0; + for (cp = yytext + 2; *cp; cp++) + { + if (*cp == '\'') + { + if (cp[1] == '\'') + result[len++] = *cp++; + /* else it must be string end quote */ + } + else if (*cp == '\\') + { + if (cp[1] != '\0') /* just a paranoid check */ + result[len++] = *(++cp); + } + else + result[len++] = *cp; + } + result[len] = '\0'; + } else { /* Token is a '...' string */ result = (char *) palloc(yyleng + 1); /* more than enough room */ len = 0; - for (cp = yytext; *cp; cp++) + for (cp = yytext + 1; *cp; cp++) { if (*cp == '\'') { if (cp[1] == '\'') result[len++] = *cp++; - /* else it must be string start or end quote */ + /* else it must be string end quote */ } else if (*cp == '\\') { |