Commit 19c21d11 authored by Bruce Momjian's avatar Bruce Momjian

Enable standard_conforming_strings to be turned on.

Kevin Grittner
parent a9c1047e
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.49 2006/03/04 22:19:31 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.50 2006/03/06 19:49:19 momjian Exp $
--> -->
<chapter Id="runtime-config"> <chapter Id="runtime-config">
<title>Server Configuration</title> <title>Server Configuration</title>
...@@ -3737,10 +3737,28 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' ...@@ -3737,10 +3737,28 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</para> </para>
<para> <para>
Escape string syntax (<literal>E'...'</>) should be used for Escape string syntax (<literal>E'...'</>) should be used for
escapes, because in future versions of backslash escape sequences, because ordinary strings have
<productname>PostgreSQL</productname> ordinary strings will have
the standard-conforming behavior of treating backslashes the standard-conforming behavior of treating backslashes
literally. literally when the <literal>standard-conforming-strings</>
option is set <literal>on</>.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-standard-conforming-strings" xreflabel="standard_conforming_strings">
<term><varname>standard_conforming_strings</varname> (<type>boolean</type>)</term>
<indexterm><primary>strings</><secondary>escape</></>
<indexterm>
<primary><varname>standard_conforming_strings</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Controls whether ordinary string literals
(<literal>'...'</>) treat backslashes literally, as specified in
the SQL standard. Applications may check this
parameter to determine how string literals will be processed.
The presence of this parameter can also be taken as an indication
that the escape string syntax (<literal>E'...'</>) is supported.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -3992,28 +4010,6 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' ...@@ -3992,28 +4010,6 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-standard-conforming-strings" xreflabel="standard_conforming_strings">
<term><varname>standard_conforming_strings</varname> (<type>boolean</type>)</term>
<indexterm><primary>strings</><secondary>escape</></>
<indexterm>
<primary><varname>standard_conforming_strings</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Reports whether ordinary string literals
(<literal>'...'</>) treat backslashes literally, as specified in
the SQL standard. The value is currently always <literal>off</>,
indicating that backslashes are treated as escapes. It is planned
that this will change to <literal>on</> in a future
<productname>PostgreSQL</productname> release when string literal
syntax changes to meet the standard. Applications may check this
parameter to determine how string literals will be processed.
The presence of this parameter can also be taken as an indication
that the escape string syntax (<literal>E'...'</>) is supported.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</sect1> </sect1>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.130 2006/03/05 15:58:34 momjian Exp $ * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.131 2006/03/06 19:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -51,13 +51,14 @@ static int xcdepth = 0; /* depth of nesting in slash-star comments */ ...@@ -51,13 +51,14 @@ static int xcdepth = 0; /* depth of nesting in slash-star comments */
static char *dolqstart; /* current $foo$ quote start string */ static char *dolqstart; /* current $foo$ quote start string */
/* /*
* GUC variable. This is a DIRECT violation of the warning given at the * GUC variables. 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; * 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. * 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 * But we shall have to live with it as a short-term thing until the switch
* to SQL-standard string syntax is complete. * to SQL-standard string syntax is complete.
*/ */
bool escape_string_warning; bool escape_string_warning;
bool standard_conforming_strings;
static bool warn_on_first_escape; static bool warn_on_first_escape;
...@@ -77,6 +78,7 @@ static void addlitchar(unsigned char ychar); ...@@ -77,6 +78,7 @@ static void addlitchar(unsigned char ychar);
static char *litbufdup(void); static char *litbufdup(void);
static int pg_err_position(void); static int pg_err_position(void);
static void check_escape_warning(void); static void check_escape_warning(void);
static void check_string_escape_warning(unsigned char ychar);
/* /*
* When we parse a token that requires multiple lexer rules to process, * When we parse a token that requires multiple lexer rules to process,
...@@ -119,7 +121,8 @@ static unsigned char unescape_single_char(unsigned char c); ...@@ -119,7 +121,8 @@ static unsigned char unescape_single_char(unsigned char c);
* <xc> extended C-style comments * <xc> extended C-style comments
* <xd> delimited identifiers (double-quoted identifiers) * <xd> delimited identifiers (double-quoted identifiers)
* <xh> hexadecimal numeric string * <xh> hexadecimal numeric string
* <xq> quoted strings * <xq> standard quoted strings
* <xe> extended quoted strings (support backslash escape sequences)
* <xdolq> $foo$ quoted strings * <xdolq> $foo$ quoted strings
*/ */
...@@ -127,6 +130,7 @@ static unsigned char unescape_single_char(unsigned char c); ...@@ -127,6 +130,7 @@ static unsigned char unescape_single_char(unsigned char c);
%x xc %x xc
%x xd %x xd
%x xh %x xh
%x xe
%x xq %x xq
%x xdolq %x xdolq
...@@ -200,6 +204,10 @@ xnstart [nN]{quote} ...@@ -200,6 +204,10 @@ xnstart [nN]{quote}
/* Quoted string that allows backslash escapes */ /* Quoted string that allows backslash escapes */
xestart [eE]{quote} xestart [eE]{quote}
xeinside [^\\']+
xeescape [\\][^0-7]
xeoctesc [\\][0-7]{1,3}
xehexesc [\\]x[0-9A-Fa-f]{1,2}
/* Extended quote /* Extended quote
* xqdouble implements embedded quote, '''' * xqdouble implements embedded quote, ''''
...@@ -207,9 +215,7 @@ xestart [eE]{quote} ...@@ -207,9 +215,7 @@ xestart [eE]{quote}
xqstart {quote} xqstart {quote}
xqdouble {quote}{quote} xqdouble {quote}{quote}
xqinside [^\\']+ xqinside [^\\']+
xqescape [\\][^0-7] xqbackslash [\\]
xqoctesc [\\][0-7]{1,3}
xqhexesc [\\]x[0-9A-Fa-f]{1,2}
/* $foo$ style quotes ("dollar quoting") /* $foo$ style quotes ("dollar quoting")
* The quoted string starts with $foo$ where "foo" is an optional string * The quoted string starts with $foo$ where "foo" is an optional string
...@@ -428,73 +434,62 @@ other . ...@@ -428,73 +434,62 @@ other .
{xqstart} { {xqstart} {
warn_on_first_escape = true; warn_on_first_escape = true;
token_start = yytext; token_start = yytext;
BEGIN(xq); if (standard_conforming_strings)
BEGIN(xq);
else
BEGIN(xe);
startlit(); startlit();
} }
{xestart} { {xestart} {
warn_on_first_escape = false; warn_on_first_escape = false;
token_start = yytext; token_start = yytext;
BEGIN(xq); BEGIN(xe);
startlit(); startlit();
} }
<xq>{quotestop} | <xq,xe>{quotestop} |
<xq>{quotefail} { <xq,xe>{quotefail} {
yyless(1); yyless(1);
BEGIN(INITIAL); BEGIN(INITIAL);
yylval.str = litbufdup(); yylval.str = litbufdup();
return SCONST; return SCONST;
} }
<xq>{xqdouble} { <xq,xe>{xqdouble} {
addlitchar('\''); addlitchar('\'');
} }
<xq>{xqinside} { <xq>{xqinside} {
addlit(yytext, yyleng); addlit(yytext, yyleng);
} }
<xq>{xqescape} { <xe>{xeinside} {
if (yytext[1] == '\'') addlit(yytext, yyleng);
{ }
if (warn_on_first_escape && escape_string_warning) <xq>{xqbackslash} {
ereport(WARNING, check_string_escape_warning(yytext[1]);
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), addlitchar('\\');
errmsg("nonstandard use of \\' in a string literal"), }
errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), <xe>{xeescape} {
errposition(pg_err_position()))); check_string_escape_warning(yytext[1]);
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_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();
addlitchar(unescape_single_char(yytext[1])); addlitchar(unescape_single_char(yytext[1]));
} }
<xq>{xqoctesc} { <xe>{xeoctesc} {
unsigned char c = strtoul(yytext+1, NULL, 8); unsigned char c = strtoul(yytext+1, NULL, 8);
check_escape_warning(); check_escape_warning();
addlitchar(c); addlitchar(c);
} }
<xq>{xqhexesc} { <xe>{xehexesc} {
unsigned char c = strtoul(yytext+2, NULL, 16); unsigned char c = strtoul(yytext+2, NULL, 16);
check_escape_warning(); check_escape_warning();
addlitchar(c); addlitchar(c);
} }
<xq>{quotecontinue} { <xq,xe>{quotecontinue} {
/* ignore */ /* ignore */
} }
<xq>. { <xe>. {
/* This is only needed for \ just before EOF */ /* This is only needed for \ just before EOF */
addlitchar(yytext[0]); addlitchar(yytext[0]);
} }
<xq><<EOF>> { yyerror("unterminated quoted string"); } <xq,xe><<EOF>> { yyerror("unterminated quoted string"); }
{dolqdelim} { {dolqdelim} {
token_start = yytext; token_start = yytext;
...@@ -875,6 +870,33 @@ unescape_single_char(unsigned char c) ...@@ -875,6 +870,33 @@ unescape_single_char(unsigned char c)
} }
} }
static void
check_string_escape_warning(unsigned char ychar)
{
if (ychar == '\'')
{
if (warn_on_first_escape && escape_string_warning)
ereport(WARNING,
(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 (ychar == '\\')
{
if (warn_on_first_escape && escape_string_warning)
ereport(WARNING,
(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();
}
static void static void
check_escape_warning(void) check_escape_warning(void)
{ {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.312 2006/03/05 15:58:49 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.313 2006/03/06 19:49:20 momjian Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -224,7 +224,6 @@ static int max_index_keys; ...@@ -224,7 +224,6 @@ static int max_index_keys;
static int max_identifier_length; static int max_identifier_length;
static int block_size; static int block_size;
static bool integer_datetimes; static bool integer_datetimes;
static bool standard_conforming_strings;
/* should be static, but commands/variable.c needs to get at these */ /* should be static, but commands/variable.c needs to get at these */
char *role_string; char *role_string;
...@@ -974,10 +973,10 @@ static struct config_bool ConfigureNamesBool[] = ...@@ -974,10 +973,10 @@ static struct config_bool ConfigureNamesBool[] =
}, },
{ {
{"standard_conforming_strings", PGC_INTERNAL, PRESET_OPTIONS, {"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
gettext_noop("'...' strings treat backslashes literally."), gettext_noop("'...' strings treat backslashes literally."),
NULL, NULL,
GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE GUC_REPORT
}, },
&standard_conforming_strings, &standard_conforming_strings,
false, NULL, NULL false, NULL, NULL
......
...@@ -415,7 +415,8 @@ ...@@ -415,7 +415,8 @@
#add_missing_from = off #add_missing_from = off
#array_nulls = on #array_nulls = on
#default_with_oids = off #default_with_oids = off
#escape_string_warning = off #escape_string_warning = off # warn about backslashes in string literals
#standard_conforming_strings = off # SQL standard string literal processing
#regex_flavor = advanced # advanced, extended, or basic #regex_flavor = advanced # advanced, extended, or basic
#sql_inheritance = on #sql_inheritance = on
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * Copyright (c) 2000-2006, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.114 2006/03/05 15:58:51 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.115 2006/03/06 19:49:20 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "common.h" #include "common.h"
...@@ -1328,6 +1328,29 @@ is_superuser(void) ...@@ -1328,6 +1328,29 @@ is_superuser(void)
} }
/*
* Test if the current session uses standard string literals.
*
* Note: this will correctly detect the setting only with a protocol-3.0
* or newer backend; otherwise it will always say "false".
*/
bool
standard_strings(void)
{
const char *val;
if (!pset.db)
return false;
val = PQparameterStatus(pset.db, "standard_conforming_strings");
if (val && strcmp(val, "on") == 0)
return true;
return false;
}
/* /*
* Return the session user of the current connection. * Return the session user of the current connection.
* *
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * Copyright (c) 2000-2006, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/common.h,v 1.46 2006/03/05 15:58:51 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/common.h,v 1.47 2006/03/06 19:49:20 momjian Exp $
*/ */
#ifndef COMMON_H #ifndef COMMON_H
#define COMMON_H #define COMMON_H
...@@ -57,6 +57,7 @@ extern PGresult *PSQLexec(const char *query, bool start_xact); ...@@ -57,6 +57,7 @@ extern PGresult *PSQLexec(const char *query, bool start_xact);
extern bool SendQuery(const char *query); extern bool SendQuery(const char *query);
extern bool is_superuser(void); extern bool is_superuser(void);
extern bool standard_strings(void);
extern const char *session_username(void); extern const char *session_username(void);
extern char *expand_tilde(char **filename); extern char *expand_tilde(char **filename);
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.16 2006/03/05 15:58:52 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.17 2006/03/06 19:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -154,7 +154,8 @@ static void emit(const char *txt, int len); ...@@ -154,7 +154,8 @@ static void emit(const char *txt, int len);
* <xc> extended C-style comments * <xc> extended C-style comments
* <xd> delimited identifiers (double-quoted identifiers) * <xd> delimited identifiers (double-quoted identifiers)
* <xh> hexadecimal numeric string * <xh> hexadecimal numeric string
* <xq> quoted strings * <xq> standard quoted strings
* <xe> extended quoted strings (support backslash escape sequences)
* <xdolq> $foo$ quoted strings * <xdolq> $foo$ quoted strings
*/ */
...@@ -162,6 +163,7 @@ static void emit(const char *txt, int len); ...@@ -162,6 +163,7 @@ static void emit(const char *txt, int len);
%x xc %x xc
%x xd %x xd
%x xh %x xh
%x xe
%x xq %x xq
%x xdolq %x xdolq
/* Additional exclusive states for psql only: lex backslash commands */ /* Additional exclusive states for psql only: lex backslash commands */
...@@ -244,16 +246,17 @@ xnstart [nN]{quote} ...@@ -244,16 +246,17 @@ xnstart [nN]{quote}
/* Quoted string that allows backslash escapes */ /* Quoted string that allows backslash escapes */
xestart [eE]{quote} xestart [eE]{quote}
xeinside [^\\']+
xeescape [\\][^0-7]
xeoctesc [\\][0-7]{1,3}
xehexesc [\\]x[0-9A-Fa-f]{1,2}
/* Extended quote /* Extended quote
* xqdouble implements embedded quote, '''' * xqdouble implements embedded quote, ''''
*/ */
xqstart {quote} xqstart {quote}
xqdouble {quote}{quote} xqdouble {quote}{quote}
xqinside [^\\']+ xqinside [^']+
xqescape [\\][^0-7]
xqoctesc [\\][0-7]{1,3}
xqhexesc [\\]x[0-9A-Fa-f]{1,2}
/* $foo$ style quotes ("dollar quoting") /* $foo$ style quotes ("dollar quoting")
* The quoted string starts with $foo$ where "foo" is an optional string * The quoted string starts with $foo$ where "foo" is an optional string
...@@ -448,38 +451,44 @@ other . ...@@ -448,38 +451,44 @@ other .
} }
{xqstart} { {xqstart} {
BEGIN(xq); if (standard_strings())
BEGIN(xq);
else
BEGIN(xe);
ECHO; ECHO;
} }
{xestart} { {xestart} {
BEGIN(xq); BEGIN(xe);
ECHO; ECHO;
} }
<xq>{quotestop} | <xq,xe>{quotestop} |
<xq>{quotefail} { <xq,xe>{quotefail} {
yyless(1); yyless(1);
BEGIN(INITIAL); BEGIN(INITIAL);
ECHO; ECHO;
} }
<xq>{xqdouble} { <xq,xe>{xqdouble} {
ECHO; ECHO;
} }
<xq>{xqinside} { <xq>{xqinside} {
ECHO; ECHO;
} }
<xq>{xqescape} { <xe>{xeinside} {
ECHO;
}
<xe>{xeescape} {
ECHO; ECHO;
} }
<xq>{xqoctesc} { <xe>{xeoctesc} {
ECHO; ECHO;
} }
<xq>{xqhexesc} { <xe>{xehexesc} {
ECHO; ECHO;
} }
<xq>{quotecontinue} { <xq,xe>{quotecontinue} {
ECHO; ECHO;
} }
<xq>. { <xe>. {
/* This is only needed for \ just before EOF */ /* This is only needed for \ just before EOF */
ECHO; ECHO;
} }
...@@ -858,13 +867,13 @@ other . ...@@ -858,13 +867,13 @@ other .
"\\r" { appendPQExpBufferChar(output_buf, '\r'); } "\\r" { appendPQExpBufferChar(output_buf, '\r'); }
"\\f" { appendPQExpBufferChar(output_buf, '\f'); } "\\f" { appendPQExpBufferChar(output_buf, '\f'); }
{xqoctesc} { {xeoctesc} {
/* octal case */ /* octal case */
appendPQExpBufferChar(output_buf, appendPQExpBufferChar(output_buf,
(char) strtol(yytext + 1, NULL, 8)); (char) strtol(yytext + 1, NULL, 8));
} }
{xqhexesc} { {xehexesc} {
/* hex case */ /* hex case */
appendPQExpBufferChar(output_buf, appendPQExpBufferChar(output_buf,
(char) strtol(yytext + 2, NULL, 16)); (char) strtol(yytext + 2, NULL, 16));
...@@ -1128,6 +1137,10 @@ psql_scan(PsqlScanState state, ...@@ -1128,6 +1137,10 @@ psql_scan(PsqlScanState state,
result = PSCAN_INCOMPLETE; result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE; *prompt = PROMPT_SINGLEQUOTE;
break; break;
case xe:
result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE;
break;
case xdolq: case xdolq:
result = PSCAN_INCOMPLETE; result = PSCAN_INCOMPLETE;
*prompt = PROMPT_DOLLARQUOTE; *prompt = PROMPT_DOLLARQUOTE;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * Copyright (c) 2000-2006, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.65 2006/03/06 18:38:11 momjian Exp $ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.66 2006/03/06 19:49:20 momjian Exp $
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
#ifndef GUC_H #ifndef GUC_H
...@@ -121,6 +121,7 @@ extern bool Australian_timezones; ...@@ -121,6 +121,7 @@ extern bool Australian_timezones;
extern bool default_with_oids; extern bool default_with_oids;
extern bool escape_string_warning; extern bool escape_string_warning;
extern bool standard_conforming_strings;
extern int log_min_error_statement; extern int log_min_error_statement;
extern int log_min_messages; extern int log_min_messages;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.144 2006/03/05 15:59:08 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.145 2006/03/06 19:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -30,7 +30,8 @@ extern YYSTYPE yylval; ...@@ -30,7 +30,8 @@ extern YYSTYPE yylval;
static int xcdepth = 0; /* depth of nesting in slash-star comments */ static int xcdepth = 0; /* depth of nesting in slash-star comments */
static char *dolqstart; /* current $foo$ quote start string */ static char *dolqstart; /* current $foo$ quote start string */
bool escape_string_warning; bool escape_string_warning;
static bool warn_on_first_escape; bool standard_conforming_strings;
static bool warn_on_first_escape;
/* /*
* literalbuf is used to accumulate literal values when multiple rules * literalbuf is used to accumulate literal values when multiple rules
...@@ -96,7 +97,8 @@ static struct _if_value ...@@ -96,7 +97,8 @@ static struct _if_value
* <xc> extended C-style comments - thomas 1997-07-12 * <xc> extended C-style comments - thomas 1997-07-12
* <xd> delimited identifiers (double-quoted identifiers) - thomas 1997-10-27 * <xd> delimited identifiers (double-quoted identifiers) - thomas 1997-10-27
* <xh> hexadecimal numeric string - thomas 1997-11-16 * <xh> hexadecimal numeric string - thomas 1997-11-16
* <xq> quoted strings - thomas 1997-07-30 * <xq> standard quoted strings - thomas 1997-07-30
* <xe> extended quoted strings (support backslash escape sequences)
* <xdolq> $foo$ quoted strings * <xdolq> $foo$ quoted strings
*/ */
...@@ -105,6 +107,7 @@ static struct _if_value ...@@ -105,6 +107,7 @@ static struct _if_value
%x xd %x xd
%x xdc %x xdc
%x xh %x xh
%x xe
%x xq %x xq
%x xdolq %x xdolq
%x xpre %x xpre
...@@ -125,6 +128,10 @@ xnstart [nN]{quote} ...@@ -125,6 +128,10 @@ xnstart [nN]{quote}
/* Quoted string that allows backslash escapes */ /* Quoted string that allows backslash escapes */
xestart [eE]{quote} xestart [eE]{quote}
xeinside [^\\']+
xeescape [\\][^0-7]
xeoctesc [\\][0-7]{1,3}
xehexesc [\\]x[0-9A-Fa-f]{1,2}
/* C version of hex number */ /* C version of hex number */
xch 0[xX][0-9A-Fa-f]* xch 0[xX][0-9A-Fa-f]*
...@@ -135,9 +142,7 @@ xch 0[xX][0-9A-Fa-f]* ...@@ -135,9 +142,7 @@ xch 0[xX][0-9A-Fa-f]*
xqstart {quote} xqstart {quote}
xqdouble {quote}{quote} xqdouble {quote}{quote}
xqinside [^\\']+ xqinside [^\\']+
xqescape [\\][^0-7] xqbackslash [\\]
xqoctesc [\\][0-7]{1,3}
xqhexesc [\\]x[0-9A-Fa-f]{1,2}
/* $foo$ style quotes ("dollar quoting") /* $foo$ style quotes ("dollar quoting")
* The quoted string starts with $foo$ where "foo" is an optional string * The quoted string starts with $foo$ where "foo" is an optional string
...@@ -405,43 +410,51 @@ cppline {space}*#(.*\\{space})*.*{newline} ...@@ -405,43 +410,51 @@ cppline {space}*#(.*\\{space})*.*{newline}
warn_on_first_escape = true; warn_on_first_escape = true;
token_start = yytext; token_start = yytext;
state_before = YYSTATE; state_before = YYSTATE;
BEGIN(xq); if (standard_conforming_strings)
BEGIN(xq);
else
BEGIN(xe);
startlit(); startlit();
} }
<C,SQL>{xestart} { <C,SQL>{xestart} {
warn_on_first_escape = false; warn_on_first_escape = false;
token_start = yytext; token_start = yytext;
state_before = YYSTATE; state_before = YYSTATE;
BEGIN(xq); BEGIN(xe);
startlit(); startlit();
} }
<xq>{quotestop} | <xq,xe>{quotestop} |
<xq>{quotefail} { <xq,xe>{quotefail} {
yyless(1); yyless(1);
BEGIN(state_before); BEGIN(state_before);
yylval.str = mm_strdup(literalbuf); yylval.str = mm_strdup(literalbuf);
return SCONST; return SCONST;
} }
<xq>{xqdouble} { addlitchar('\''); } <xq,xe>{xqdouble} { addlitchar('\''); }
<xq>{xqinside} { addlit(yytext, yyleng); } <xq>{xqinside} { addlit(yytext, yyleng); }
<xq>{xqescape} { <xe>{xeinside} { addlit(yytext, yyleng); }
<xq>{xqbackslash} {
check_escape_warning();
addlitchar('\\');
}
<xe>{xeescape} {
check_escape_warning(); check_escape_warning();
addlit(yytext, yyleng); addlit(yytext, yyleng);
} }
<xq>{xqoctesc} { <xe>{xeoctesc} {
check_escape_warning(); check_escape_warning();
addlit(yytext, yyleng); addlit(yytext, yyleng);
} }
<xq>{xqhexesc} { <xe>{xehexesc} {
check_escape_warning(); check_escape_warning();
addlit(yytext, yyleng); addlit(yytext, yyleng);
} }
<xq>{quotecontinue} { /* ignore */ } <xq,xe>{quotecontinue} { /* ignore */ }
<xq>{other} { <xe>. {
/* This is only needed for \ just before EOF */ /* This is only needed for \ just before EOF */
addlitchar(yytext[0]); addlitchar(yytext[0]);
} }
<xq><<EOF>> { mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted string"); } <xq,xe><<EOF>> { mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted string"); }
<SQL>{dolqfailed} { <SQL>{dolqfailed} {
/* throw back all but the initial "$" */ /* throw back all but the initial "$" */
yyless(1); yyless(1);
......
...@@ -193,13 +193,13 @@ SELECT SUBSTRING('abcdefg' FROM 'b(.*)f') AS "cde"; ...@@ -193,13 +193,13 @@ SELECT SUBSTRING('abcdefg' FROM 'b(.*)f') AS "cde";
(1 row) (1 row)
-- PostgreSQL extension to allow using back reference in replace string; -- PostgreSQL extension to allow using back reference in replace string;
SELECT regexp_replace('1112223333', '(\\d{3})(\\d{3})(\\d{4})', '(\\1) \\2-\\3'); SELECT regexp_replace('1112223333', E'(\\d{3})(\\d{3})(\\d{4})', E'(\\1) \\2-\\3');
regexp_replace regexp_replace
---------------- ----------------
(111) 222-3333 (111) 222-3333
(1 row) (1 row)
SELECT regexp_replace('AAA BBB CCC ', '\\s+', ' ', 'g'); SELECT regexp_replace('AAA BBB CCC ', E'\\s+', ' ', 'g');
regexp_replace regexp_replace
---------------- ----------------
AAA BBB CCC AAA BBB CCC
...@@ -895,3 +895,86 @@ select md5('12345678901234567890123456789012345678901234567890123456789012345678 ...@@ -895,3 +895,86 @@ select md5('12345678901234567890123456789012345678901234567890123456789012345678
t t
(1 row) (1 row)
--
-- test behavior of escape_string_warning and standard_conforming_strings options
--
set escape_string_warning = off;
set standard_conforming_strings = off;
show escape_string_warning;
escape_string_warning
-----------------------
off
(1 row)
show standard_conforming_strings;
standard_conforming_strings
-----------------------------
off
(1 row)
set escape_string_warning = on;
set standard_conforming_strings = on;
show escape_string_warning;
escape_string_warning
-----------------------
on
(1 row)
show standard_conforming_strings;
standard_conforming_strings
-----------------------------
on
(1 row)
select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6;
WARNING: nonstandard use of escape in a string literal at character 8
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 23
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 40
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 59
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 76
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
WARNING: nonstandard use of escape in a string literal at character 93
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'.
f1 | f2 | f3 | f4 | f5 | f6
-------+--------+---------+-------+--------+----
a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\
(1 row)
set standard_conforming_strings = off;
select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as f6;
WARNING: nonstandard use of \\ in a string literal at character 8
HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 24
HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 42
HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 62
HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 80
HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
WARNING: nonstandard use of \\ in a string literal at character 98
HINT: Use the escape string syntax for backslashes, e.g., E'\\'.
f1 | f2 | f3 | f4 | f5 | f6
-------+--------+---------+-------+--------+----
a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\
(1 row)
set escape_string_warning = off;
set standard_conforming_strings = on;
select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6;
f1 | f2 | f3 | f4 | f5 | f6
-------+--------+---------+-------+--------+----
a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\
(1 row)
set standard_conforming_strings = off;
select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as f6;
f1 | f2 | f3 | f4 | f5 | f6
-------+--------+---------+-------+--------+----
a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\
(1 row)
...@@ -81,8 +81,8 @@ SELECT SUBSTRING('abcdefg' FROM 'c.e') AS "cde"; ...@@ -81,8 +81,8 @@ SELECT SUBSTRING('abcdefg' FROM 'c.e') AS "cde";
SELECT SUBSTRING('abcdefg' FROM 'b(.*)f') AS "cde"; SELECT SUBSTRING('abcdefg' FROM 'b(.*)f') AS "cde";
-- PostgreSQL extension to allow using back reference in replace string; -- PostgreSQL extension to allow using back reference in replace string;
SELECT regexp_replace('1112223333', '(\\d{3})(\\d{3})(\\d{4})', '(\\1) \\2-\\3'); SELECT regexp_replace('1112223333', E'(\\d{3})(\\d{3})(\\d{4})', E'(\\1) \\2-\\3');
SELECT regexp_replace('AAA BBB CCC ', '\\s+', ' ', 'g'); SELECT regexp_replace('AAA BBB CCC ', E'\\s+', ' ', 'g');
SELECT regexp_replace('AAA', '^|$', 'Z', 'g'); SELECT regexp_replace('AAA', '^|$', 'Z', 'g');
SELECT regexp_replace('AAA aaa', 'A+', 'Z', 'gi'); SELECT regexp_replace('AAA aaa', 'A+', 'Z', 'gi');
-- invalid option of REGEXP_REPLACE -- invalid option of REGEXP_REPLACE
...@@ -352,3 +352,33 @@ select md5('abcdefghijklmnopqrstuvwxyz'::bytea) = 'c3fcd3d76192e4007dfb496cca67e ...@@ -352,3 +352,33 @@ select md5('abcdefghijklmnopqrstuvwxyz'::bytea) = 'c3fcd3d76192e4007dfb496cca67e
select md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'::bytea) = 'd174ab98d277d9f5a5611c2c9f419d9f' AS "TRUE"; select md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'::bytea) = 'd174ab98d277d9f5a5611c2c9f419d9f' AS "TRUE";
select md5('12345678901234567890123456789012345678901234567890123456789012345678901234567890'::bytea) = '57edf4a22be3c955ac49da2e2107b67a' AS "TRUE"; select md5('12345678901234567890123456789012345678901234567890123456789012345678901234567890'::bytea) = '57edf4a22be3c955ac49da2e2107b67a' AS "TRUE";
--
-- test behavior of escape_string_warning and standard_conforming_strings options
--
set escape_string_warning = off;
set standard_conforming_strings = off;
show escape_string_warning;
show standard_conforming_strings;
set escape_string_warning = on;
set standard_conforming_strings = on;
show escape_string_warning;
show standard_conforming_strings;
select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6;
set standard_conforming_strings = off;
select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as f6;
set escape_string_warning = off;
set standard_conforming_strings = on;
select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' as f3, 'abcd\' as f4, 'ab\''cd' as f5, '\\' as f6;
set standard_conforming_strings = off;
select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as f6;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment