aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/config.sgml48
-rw-r--r--src/backend/parser/scan.l100
-rw-r--r--src/backend/utils/misc/guc.c7
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample3
-rw-r--r--src/bin/psql/common.c25
-rw-r--r--src/bin/psql/common.h3
-rw-r--r--src/bin/psql/psqlscan.l49
-rw-r--r--src/include/utils/guc.h3
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l47
-rw-r--r--src/test/regress/expected/strings.out87
-rw-r--r--src/test/regress/sql/strings.sql34
11 files changed, 294 insertions, 112 deletions
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 77a742e0450..e255df3e132 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,5 +1,5 @@
<!--
-$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">
<title>Server Configuration</title>
@@ -3737,10 +3737,28 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</para>
<para>
Escape string syntax (<literal>E'...'</>) should be used for
- escapes, because in future versions of
- <productname>PostgreSQL</productname> ordinary strings will have
+ backslash escape sequences, because ordinary strings have
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>
</listitem>
</varlistentry>
@@ -3992,28 +4010,6 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</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>
- 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>
</sect1>
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 10193bcff59..e277920ee20 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.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 */
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;
* 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;
+bool standard_conforming_strings;
static bool warn_on_first_escape;
@@ -77,6 +78,7 @@ static void addlitchar(unsigned char ychar);
static char *litbufdup(void);
static int pg_err_position(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,
@@ -119,7 +121,8 @@ static unsigned char unescape_single_char(unsigned char c);
* <xc> extended C-style comments
* <xd> delimited identifiers (double-quoted identifiers)
* <xh> hexadecimal numeric string
- * <xq> quoted strings
+ * <xq> standard quoted strings
+ * <xe> extended quoted strings (support backslash escape sequences)
* <xdolq> $foo$ quoted strings
*/
@@ -127,6 +130,7 @@ static unsigned char unescape_single_char(unsigned char c);
%x xc
%x xd
%x xh
+%x xe
%x xq
%x xdolq
@@ -200,6 +204,10 @@ xnstart [nN]{quote}
/* Quoted string that allows backslash escapes */
xestart [eE]{quote}
+xeinside [^\\']+
+xeescape [\\][^0-7]
+xeoctesc [\\][0-7]{1,3}
+xehexesc [\\]x[0-9A-Fa-f]{1,2}
/* Extended quote
* xqdouble implements embedded quote, ''''
@@ -207,9 +215,7 @@ xestart [eE]{quote}
xqstart {quote}
xqdouble {quote}{quote}
xqinside [^\\']+
-xqescape [\\][^0-7]
-xqoctesc [\\][0-7]{1,3}
-xqhexesc [\\]x[0-9A-Fa-f]{1,2}
+xqbackslash [\\]
/* $foo$ style quotes ("dollar quoting")
* The quoted string starts with $foo$ where "foo" is an optional string
@@ -428,73 +434,62 @@ other .
{xqstart} {
warn_on_first_escape = true;
token_start = yytext;
- BEGIN(xq);
+ if (standard_conforming_strings)
+ BEGIN(xq);
+ else
+ BEGIN(xe);
startlit();
}
{xestart} {
warn_on_first_escape = false;
token_start = yytext;
- BEGIN(xq);
+ BEGIN(xe);
startlit();
}
-<xq>{quotestop} |
-<xq>{quotefail} {
+<xq,xe>{quotestop} |
+<xq,xe>{quotefail} {
yyless(1);
BEGIN(INITIAL);
yylval.str = litbufdup();
return SCONST;
}
-<xq>{xqdouble} {
+<xq,xe>{xqdouble} {
addlitchar('\'');
}
<xq>{xqinside} {
addlit(yytext, yyleng);
}
-<xq>{xqescape} {
- 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 '' 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_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();
+<xe>{xeinside} {
+ addlit(yytext, yyleng);
+ }
+<xq>{xqbackslash} {
+ check_string_escape_warning(yytext[1]);
+ addlitchar('\\');
+ }
+<xe>{xeescape} {
+ check_string_escape_warning(yytext[1]);
addlitchar(unescape_single_char(yytext[1]));
}
-<xq>{xqoctesc} {
+<xe>{xeoctesc} {
unsigned char c = strtoul(yytext+1, NULL, 8);
check_escape_warning();
addlitchar(c);
}
-<xq>{xqhexesc} {
+<xe>{xehexesc} {
unsigned char c = strtoul(yytext+2, NULL, 16);
check_escape_warning();
addlitchar(c);
}
-<xq>{quotecontinue} {
+<xq,xe>{quotecontinue} {
/* ignore */
}
-<xq>. {
+<xe>. {
/* This is only needed for \ just before EOF */
addlitchar(yytext[0]);
}
-<xq><<EOF>> { yyerror("unterminated quoted string"); }
+<xq,xe><<EOF>> { yyerror("unterminated quoted string"); }
{dolqdelim} {
token_start = yytext;
@@ -876,6 +871,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
check_escape_warning(void)
{
if (warn_on_first_escape && escape_string_warning)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 67eb67144f0..16180247bfc 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.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;
static int max_identifier_length;
static int block_size;
static bool integer_datetimes;
-static bool standard_conforming_strings;
/* should be static, but commands/variable.c needs to get at these */
char *role_string;
@@ -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."),
NULL,
- GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
+ GUC_REPORT
},
&standard_conforming_strings,
false, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 731f9ff6c2e..071839cfd89 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -415,7 +415,8 @@
#add_missing_from = off
#array_nulls = on
#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
#sql_inheritance = on
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index ee1333e1ddc..07f4d22c070 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -3,7 +3,7 @@
*
* 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 "common.h"
@@ -1329,6 +1329,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.
*
* Note: this will correctly detect the session user only with a
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index 70bb10d6700..b12ccdec575 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -3,7 +3,7 @@
*
* 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
#define COMMON_H
@@ -57,6 +57,7 @@ extern PGresult *PSQLexec(const char *query, bool start_xact);
extern bool SendQuery(const char *query);
extern bool is_superuser(void);
+extern bool standard_strings(void);
extern const char *session_username(void);
extern char *expand_tilde(char **filename);
diff --git a/src/bin/psql/psqlscan.l b/src/bin/psql/psqlscan.l
index 2341527ccbf..6c04aaf30ba 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.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);
* <xc> extended C-style comments
* <xd> delimited identifiers (double-quoted identifiers)
* <xh> hexadecimal numeric string
- * <xq> quoted strings
+ * <xq> standard quoted strings
+ * <xe> extended quoted strings (support backslash escape sequences)
* <xdolq> $foo$ quoted strings
*/
@@ -162,6 +163,7 @@ static void emit(const char *txt, int len);
%x xc
%x xd
%x xh
+%x xe
%x xq
%x xdolq
/* Additional exclusive states for psql only: lex backslash commands */
@@ -244,16 +246,17 @@ xnstart [nN]{quote}
/* Quoted string that allows backslash escapes */
xestart [eE]{quote}
+xeinside [^\\']+
+xeescape [\\][^0-7]
+xeoctesc [\\][0-7]{1,3}
+xehexesc [\\]x[0-9A-Fa-f]{1,2}
/* Extended quote
* xqdouble implements embedded quote, ''''
*/
xqstart {quote}
xqdouble {quote}{quote}
-xqinside [^\\']+
-xqescape [\\][^0-7]
-xqoctesc [\\][0-7]{1,3}
-xqhexesc [\\]x[0-9A-Fa-f]{1,2}
+xqinside [^']+
/* $foo$ style quotes ("dollar quoting")
* The quoted string starts with $foo$ where "foo" is an optional string
@@ -448,38 +451,44 @@ other .
}
{xqstart} {
- BEGIN(xq);
+ if (standard_strings())
+ BEGIN(xq);
+ else
+ BEGIN(xe);
ECHO;
}
{xestart} {
- BEGIN(xq);
+ BEGIN(xe);
ECHO;
}
-<xq>{quotestop} |
-<xq>{quotefail} {
+<xq,xe>{quotestop} |
+<xq,xe>{quotefail} {
yyless(1);
BEGIN(INITIAL);
ECHO;
}
-<xq>{xqdouble} {
+<xq,xe>{xqdouble} {
ECHO;
}
<xq>{xqinside} {
ECHO;
}
-<xq>{xqescape} {
+<xe>{xeinside} {
+ ECHO;
+ }
+<xe>{xeescape} {
ECHO;
}
-<xq>{xqoctesc} {
+<xe>{xeoctesc} {
ECHO;
}
-<xq>{xqhexesc} {
+<xe>{xehexesc} {
ECHO;
}
-<xq>{quotecontinue} {
+<xq,xe>{quotecontinue} {
ECHO;
}
-<xq>. {
+<xe>. {
/* This is only needed for \ just before EOF */
ECHO;
}
@@ -858,13 +867,13 @@ other .
"\\r" { appendPQExpBufferChar(output_buf, '\r'); }
"\\f" { appendPQExpBufferChar(output_buf, '\f'); }
-{xqoctesc} {
+{xeoctesc} {
/* octal case */
appendPQExpBufferChar(output_buf,
(char) strtol(yytext + 1, NULL, 8));
}
-{xqhexesc} {
+{xehexesc} {
/* hex case */
appendPQExpBufferChar(output_buf,
(char) strtol(yytext + 2, NULL, 16));
@@ -1128,6 +1137,10 @@ psql_scan(PsqlScanState state,
result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE;
break;
+ case xe:
+ result = PSCAN_INCOMPLETE;
+ *prompt = PROMPT_SINGLEQUOTE;
+ break;
case xdolq:
result = PSCAN_INCOMPLETE;
*prompt = PROMPT_DOLLARQUOTE;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index a55a89b90d8..6e444756f8b 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
* 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
@@ -121,6 +121,7 @@ extern bool Australian_timezones;
extern bool default_with_oids;
extern bool escape_string_warning;
+extern bool standard_conforming_strings;
extern int log_min_error_statement;
extern int log_min_messages;
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 7e6237c0510..67f2517d21f 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -12,7 +12,7 @@
*
*
* 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;
static int xcdepth = 0; /* depth of nesting in slash-star comments */
static char *dolqstart; /* current $foo$ quote start string */
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
@@ -96,7 +97,8 @@ static struct _if_value
* <xc> extended C-style comments - thomas 1997-07-12
* <xd> delimited identifiers (double-quoted identifiers) - thomas 1997-10-27
* <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
*/
@@ -105,6 +107,7 @@ static struct _if_value
%x xd
%x xdc
%x xh
+%x xe
%x xq
%x xdolq
%x xpre
@@ -125,6 +128,10 @@ xnstart [nN]{quote}
/* Quoted string that allows backslash escapes */
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 */
xch 0[xX][0-9A-Fa-f]*
@@ -135,9 +142,7 @@ xch 0[xX][0-9A-Fa-f]*
xqstart {quote}
xqdouble {quote}{quote}
xqinside [^\\']+
-xqescape [\\][^0-7]
-xqoctesc [\\][0-7]{1,3}
-xqhexesc [\\]x[0-9A-Fa-f]{1,2}
+xqbackslash [\\]
/* $foo$ style quotes ("dollar quoting")
* The quoted string starts with $foo$ where "foo" is an optional string
@@ -405,43 +410,51 @@ cppline {space}*#(.*\\{space})*.*{newline}
warn_on_first_escape = true;
token_start = yytext;
state_before = YYSTATE;
- BEGIN(xq);
+ if (standard_conforming_strings)
+ BEGIN(xq);
+ else
+ BEGIN(xe);
startlit();
}
<C,SQL>{xestart} {
warn_on_first_escape = false;
token_start = yytext;
state_before = YYSTATE;
- BEGIN(xq);
+ BEGIN(xe);
startlit();
}
-<xq>{quotestop} |
-<xq>{quotefail} {
+<xq,xe>{quotestop} |
+<xq,xe>{quotefail} {
yyless(1);
BEGIN(state_before);
yylval.str = mm_strdup(literalbuf);
return SCONST;
}
-<xq>{xqdouble} { addlitchar('\''); }
+<xq,xe>{xqdouble} { addlitchar('\''); }
<xq>{xqinside} { addlit(yytext, yyleng); }
-<xq>{xqescape} {
+<xe>{xeinside} { addlit(yytext, yyleng); }
+<xq>{xqbackslash} {
+ check_escape_warning();
+ addlitchar('\\');
+ }
+<xe>{xeescape} {
check_escape_warning();
addlit(yytext, yyleng);
}
-<xq>{xqoctesc} {
+<xe>{xeoctesc} {
check_escape_warning();
addlit(yytext, yyleng);
}
-<xq>{xqhexesc} {
+<xe>{xehexesc} {
check_escape_warning();
addlit(yytext, yyleng);
}
-<xq>{quotecontinue} { /* ignore */ }
-<xq>{other} {
+<xq,xe>{quotecontinue} { /* ignore */ }
+<xe>. {
/* This is only needed for \ just before EOF */
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} {
/* throw back all but the initial "$" */
yyless(1);
diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out
index d05ce562997..6faf3c69ad5 100644
--- a/src/test/regress/expected/strings.out
+++ b/src/test/regress/expected/strings.out
@@ -193,13 +193,13 @@ SELECT SUBSTRING('abcdefg' FROM 'b(.*)f') AS "cde";
(1 row)
-- 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
----------------
(111) 222-3333
(1 row)
-SELECT regexp_replace('AAA BBB CCC ', '\\s+', ' ', 'g');
+SELECT regexp_replace('AAA BBB CCC ', E'\\s+', ' ', 'g');
regexp_replace
----------------
AAA BBB CCC
@@ -895,3 +895,86 @@ select md5('12345678901234567890123456789012345678901234567890123456789012345678
t
(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)
+
diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql
index 620aabe8ae6..570d9a27f46 100644
--- a/src/test/regress/sql/strings.sql
+++ b/src/test/regress/sql/strings.sql
@@ -81,8 +81,8 @@ SELECT SUBSTRING('abcdefg' FROM 'c.e') AS "cde";
SELECT SUBSTRING('abcdefg' FROM 'b(.*)f') AS "cde";
-- 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('AAA BBB CCC ', '\\s+', ' ', 'g');
+SELECT regexp_replace('1112223333', E'(\\d{3})(\\d{3})(\\d{4})', E'(\\1) \\2-\\3');
+SELECT regexp_replace('AAA BBB CCC ', E'\\s+', ' ', 'g');
SELECT regexp_replace('AAA', '^|$', 'Z', 'g');
SELECT regexp_replace('AAA aaa', 'A+', 'Z', 'gi');
-- invalid option of REGEXP_REPLACE
@@ -352,3 +352,33 @@ select md5('abcdefghijklmnopqrstuvwxyz'::bytea) = 'c3fcd3d76192e4007dfb496cca67e
select md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'::bytea) = 'd174ab98d277d9f5a5611c2c9f419d9f' 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;