提交 bb3cce4e 编写于 作者: B Bruce Momjian

Add E'' syntax so eventually normal strings can treat backslashes

literally.

Add GUC variables:

        "escape_string_warning" - warn about backslashes in non-E strings
        "escape_string_syntax" - supports E'' syntax?
        "standard_compliant_strings" - treats backslashes literally in ''

Update code to use E'' when escapes are used.
上级 c96375a3
......@@ -47,37 +47,37 @@ SELECT '1 2'::tsvector;
'1' '2'
(1 row)
SELECT '\'1 2\''::tsvector;
SELECT '''1 2'''::tsvector;
tsvector
----------
'1 2'
(1 row)
SELECT '\'1 \\\'2\''::tsvector;
SELECT E'''1 \\''2'''::tsvector;
tsvector
----------
'1 \'2'
(1 row)
SELECT '\'1 \\\'2\'3'::tsvector;
SELECT E'''1 \\''2''3'::tsvector;
tsvector
-------------
'3' '1 \'2'
(1 row)
SELECT '\'1 \\\'2\' 3'::tsvector;
SELECT E'''1 \\''2'' 3'::tsvector;
tsvector
-------------
'3' '1 \'2'
(1 row)
SELECT '\'1 \\\'2\' \' 3\' 4 '::tsvector;
SELECT E'''1 \\''2'' '' 3'' 4 '::tsvector;
tsvector
------------------
'4' ' 3' '1 \'2'
(1 row)
select '\'w\':4A,3B,2C,1D,5 a:8';
select '''w'':4A,3B,2C,1D,5 a:8';
?column?
-----------------------
'w':4A,3B,2C,1D,5 a:8
......@@ -126,13 +126,13 @@ SELECT ' 1 '::tsquery;
'1'
(1 row)
SELECT '\'1 2\''::tsquery;
SELECT '''1 2'''::tsquery;
tsquery
---------
'1 2'
(1 row)
SELECT '\'1 \\\'2\''::tsquery;
SELECT E'''1 \\''2'''::tsquery;
tsquery
---------
'1 \'2'
......@@ -330,13 +330,13 @@ SELECT '1&(2&(4&(5|!6)))'::tsquery;
'1' & '2' & '4' & ( '5' | !'6' )
(1 row)
SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::tsquery;
SELECT E'1&(''2''&('' 4''&(\\|5 | ''6 \\'' !|&'')))'::tsquery;
tsquery
------------------------------------------
'1' & '2' & ' 4' & ( '|5' | '6 \' !|&' )
(1 row)
SELECT '\'the wether\':dc & \' sKies \':BC & a:d b:a';
SELECT '''the wether'':dc & '' sKies '':BC & a:d b:a';
?column?
------------------------------------------
'the wether':dc & ' sKies ':BC & a:d b:a
......@@ -382,7 +382,7 @@ select * from token_type('default');
23 | entity | HTML Entity
(23 rows)
select * from parse('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
select * from parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty');
tokid | token
......@@ -529,7 +529,7 @@ select * from parse('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc
1 | qwerty
(138 rows)
SELECT to_tsvector('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
SELECT to_tsvector('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty');
to_tsvector
......@@ -543,7 +543,7 @@ SELECT length(to_tsvector('default', '345 qw'));
2
(1 row)
SELECT length(to_tsvector('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
SELECT length(to_tsvector('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty'));
length
......@@ -563,7 +563,7 @@ select to_tsquery('simple', 'qwe & sKies ');
'qwe' & 'skies'
(1 row)
select to_tsquery('default', '\'the wether\':dc & \' sKies \':BC ');
select to_tsquery('default', '''the wether'':dc & '' sKies '':BC ');
to_tsquery
------------------------
'wether':CD & 'sky':BC
......@@ -729,7 +729,7 @@ SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
(1 row)
drop trigger tsvectorupdate on test_tsvector;
create function wow(text) returns text as 'select $1 || \' copyright\'; ' language sql;
create function wow(text) returns text as 'select $1 || '' copyright''; ' language sql;
create trigger tsvectorupdate before update or insert on test_tsvector
for each row execute procedure tsearch2(a, wow, t);
insert into test_tsvector (t) values ('345 qwerty');
......
......@@ -12,12 +12,12 @@ SELECT '1 '::tsvector;
SELECT ' 1'::tsvector;
SELECT ' 1 '::tsvector;
SELECT '1 2'::tsvector;
SELECT '\'1 2\''::tsvector;
SELECT '\'1 \\\'2\''::tsvector;
SELECT '\'1 \\\'2\'3'::tsvector;
SELECT '\'1 \\\'2\' 3'::tsvector;
SELECT '\'1 \\\'2\' \' 3\' 4 '::tsvector;
select '\'w\':4A,3B,2C,1D,5 a:8';
SELECT '''1 2'''::tsvector;
SELECT E'''1 \\''2'''::tsvector;
SELECT E'''1 \\''2''3'::tsvector;
SELECT E'''1 \\''2'' 3'::tsvector;
SELECT E'''1 \\''2'' '' 3'' 4 '::tsvector;
select '''w'':4A,3B,2C,1D,5 a:8';
select 'a:3A b:2a'::tsvector || 'ba:1234 a:1B';
select setweight('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd zxc:81,567,222A'::tsvector, 'c');
select strip('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd'::tsvector);
......@@ -28,8 +28,8 @@ SELECT '1'::tsquery;
SELECT '1 '::tsquery;
SELECT ' 1'::tsquery;
SELECT ' 1 '::tsquery;
SELECT '\'1 2\''::tsquery;
SELECT '\'1 \\\'2\''::tsquery;
SELECT '''1 2'''::tsquery;
SELECT E'''1 \\''2'''::tsquery;
SELECT '!1'::tsquery;
SELECT '1|2'::tsquery;
SELECT '1|!2'::tsquery;
......@@ -62,31 +62,31 @@ SELECT '1&(2&(4&(5&6)))'::tsquery;
SELECT '1&2&4&5&6'::tsquery;
SELECT '1&(2&(4&(5|6)))'::tsquery;
SELECT '1&(2&(4&(5|!6)))'::tsquery;
SELECT '1&(\'2\'&(\' 4\'&(\\|5 | \'6 \\\' !|&\')))'::tsquery;
SELECT '\'the wether\':dc & \' sKies \':BC & a:d b:a';
SELECT E'1&(''2''&('' 4''&(\\|5 | ''6 \\'' !|&'')))'::tsquery;
SELECT '''the wether'':dc & '' sKies '':BC & a:d b:a';
select lexize('simple', 'ASD56 hsdkf');
select lexize('en_stem', 'SKIES Problems identity');
select * from token_type('default');
select * from parse('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
select * from parse('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty');
SELECT to_tsvector('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
SELECT to_tsvector('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty');
SELECT length(to_tsvector('default', '345 qw'));
SELECT length(to_tsvector('default', '345 qwe@efd.r \' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
SELECT length(to_tsvector('default', '345 qwe@efd.r '' http://www.com/ http://aew.werc.ewr/?ad=qwe&dw 1aew.werc.ewr/?ad=qwe&dw 2aew.werc.ewr http://3aew.werc.ewr/?ad=qwe&dw http://4aew.werc.ewr http://5aew.werc.ewr:8100/? ad=qwe&dw 6aew.werc.ewr:8100/?ad=qwe&dw 7aew.werc.ewr:8100/?ad=qwe&dw=%20%32 +4.0e-10 qwe qwe qwqwe 234.435 455 5.005 teodor@stack.net qwe-wer asdf <fr>qwer jf sdjk<we hjwer <werrwe> ewr1> ewri2 <a href="qwe<qwe>">
/usr/local/fff /awdf/dwqe/4325 rewt/ewr wefjn /wqe-324/ewr gist.h gist.h.c gist.c. readline 4.2 4.2. 4.2, readline-4.2 readline-4.2. 234
<i <b> wow < jqw <> qwerty'));
select to_tsquery('default', 'qwe & sKies ');
select to_tsquery('simple', 'qwe & sKies ');
select to_tsquery('default', '\'the wether\':dc & \' sKies \':BC ');
select to_tsquery('default', '''the wether'':dc & '' sKies '':BC ');
select to_tsquery('default', 'asd&(and|fghj)');
select to_tsquery('default', '(asd&and)|fghj');
select to_tsquery('default', '(asd&!and)|fghj');
......@@ -135,7 +135,7 @@ UPDATE test_tsvector SET t = null WHERE t = '345 qwerty';
SELECT count(*) FROM test_tsvector WHERE a @@ to_tsquery('345&qwerty');
drop trigger tsvectorupdate on test_tsvector;
create function wow(text) returns text as 'select $1 || \' copyright\'; ' language sql;
create function wow(text) returns text as 'select $1 || '' copyright''; ' language sql;
create trigger tsvectorupdate before update or insert on test_tsvector
for each row execute procedure tsearch2(a, wow, t);
insert into test_tsvector (t) values ('345 qwerty');
......
<!--
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.330 2005/06/21 04:02:30 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.331 2005/06/26 03:03:17 momjian Exp $
-->
<chapter Id="runtime">
......@@ -3757,6 +3757,30 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem>
</varlistentry>
<varlistentry id="guc-escape-string-warning" xreflabel="escape_string_warning">
<term><varname>escape_string_warning</varname> (<type>boolean</type>)</term>
<indexterm><primary>strings</><secondary>escape</></>
<indexterm>
<primary><varname>escape_string_warning</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
When <literal>on</>, a warning is issued if a backslash
(<literal>\</>) appears in a ordinary, non-escape syntax
(<literal>''</>) string. To log the statement that generated the
warning, set <varname>log_min_error_statement</> to
<literal>error</>. The default is off.
</para>
<para>
Escape string syntax (<literal>E''</>) should be used for
escapes, because in future versions of
<productname>PostgreSQL</productname> ordinary strings will have
the standard-compliant behavior of treating backslashes
literally.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3 id="runtime-config-compatible-clients">
......@@ -3964,6 +3988,37 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem>
</varlistentry>
<varlistentry id="guc-escape-string-syntax" xreflabel="escape_string_syntax">
<term><varname>escape_string_syntax</varname> (<type>boolean</type>)</term>
<indexterm><primary>strings</><secondary>escape</></>
<indexterm>
<primary><varname>escape_string_syntax</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Reports whether escape string syntax (<literal>E''</>) is
supported. This variable is used by applications that need to
determine if escape string syntax can be used in their code.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-sql-standard-strings" xreflabel="standard_compliant_strings">
<term><varname>standard_compliant_strings</varname> (<type>boolean</type>)</term>
<indexterm><primary>strings</><secondary>escape</></>
<indexterm>
<primary><varname>standard_compliant_strings</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Reports whether ordinary, non-escape syntax strings
(<literal>''</>) treat backslashes literally, as specified in
the SQL standard. This variable is used by applications that
need to know how ordinary strings are processed`.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
......
<!--
$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.100 2005/06/02 01:23:08 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.101 2005/06/26 03:03:21 momjian Exp $
-->
<chapter id="sql-syntax">
......@@ -247,9 +247,10 @@ UPDATE "my_table" SET "a" = 5;
write two adjacent single quotes, e.g.
<literal>'Dianne''s horse'</literal>.
<productname>PostgreSQL</productname> also allows single quotes
to be escaped with a backslash (<literal>\</literal>), so for
example the same string could be written
<literal>'Dianne\'s horse'</literal>.
to be escaped with a backslash (<literal>\'</literal>). However,
future versions of <productname>PostgreSQL</productname> will not
support this so applications using this should convert to the
standard-compliant method outlined above.
</para>
<para>
......@@ -268,6 +269,20 @@ UPDATE "my_table" SET "a" = 5;
include a backslash in a string constant, write two backslashes.
</para>
<note>
<para>
While ordinary strings now support C-style backslash escapes,
future versions will generate warnings for such usage and
eventually treat backslashes as literal characters to be
standard-compliant. The proper way to specify escape processing is
to use the escape string syntax to indicate that escape
processing is desired. Escape string syntax is specified by placing
the the letter <literal>E</literal> (upper or lower case) before
the string, e.g. <literal>E'\041'</>. This method will work in all
future versions of <productname>PostgreSQL</productname>.
</para>
</note>
<para>
The character with the code zero cannot be in a string constant.
</para>
......
......@@ -24,7 +24,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.125 2005/06/15 16:28:06 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.126 2005/06/26 03:03:38 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -48,7 +48,9 @@
extern YYSTYPE yylval;
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 */
static bool warn_on_first_escape;
bool escape_string_warning;
/*
* literalbuf is used to accumulate literal values when multiple rules
......@@ -64,6 +66,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 void check_escape_warning(void);
/*
* When we parse a token that requires multiple lexer rules to process,
......@@ -185,6 +188,10 @@ xhinside [^']*
/* National character */
xnstart [nN]{quote}
/* Quote string does not warn about escapes */
xestart [eE]{quote}
xeinside [^']*
/* Extended quote
* xqdouble implements embedded quote, ''''
*/
......@@ -410,6 +417,13 @@ other .
}
{xqstart} {
warn_on_first_escape = true;
token_start = yytext;
BEGIN(xq);
startlit();
}
{xestart} {
warn_on_first_escape = false;
token_start = yytext;
BEGIN(xq);
startlit();
......@@ -428,14 +442,36 @@ other .
addlit(yytext, yyleng);
}
<xq>{xqescape} {
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 '' to place quotes in strings, or use the escape string syntax (E'').")));
}
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'\\\\'.")));
}
else
check_escape_warning();
addlitchar(unescape_single_char(yytext[1]));
}
<xq>{xqoctesc} {
unsigned char c = strtoul(yytext+1, NULL, 8);
check_escape_warning();
addlitchar(c);
}
<xq>{xqhexesc} {
unsigned char c = strtoul(yytext+2, NULL, 16);
check_escape_warning();
addlitchar(c);
}
<xq>{quotecontinue} {
......@@ -810,3 +846,14 @@ unescape_single_char(unsigned char c)
return c;
}
}
static void
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'.")));
warn_on_first_escape = false; /* warn only once per string */
}
......@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.268 2005/06/17 22:32:47 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.269 2005/06/26 03:03:41 momjian Exp $
*
*--------------------------------------------------------------------
*/
......@@ -189,7 +189,9 @@ static int max_function_args;
static int max_index_keys;
static int max_identifier_length;
static int block_size;
static bool integer_datetimes;
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 */
char *session_authorization_string;
......@@ -873,6 +875,35 @@ static struct config_bool ConfigureNamesBool[] =
false, NULL, NULL
},
{
{"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
gettext_noop("Warn about backslash escapes in ordinary, non-escape-syntax strings."),
NULL
},
&escape_string_warning,
false, NULL, NULL
},
{
{"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."),
NULL,
GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&standard_compliant_strings,
false, NULL, NULL
},
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL
......
......@@ -330,6 +330,7 @@
#regex_flavor = advanced # advanced, extended, or basic
#sql_inheritance = true
#default_with_oids = false
#escape_string_warning = false
# - Other Platforms & Clients -
......
......@@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD.
*
* $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.85 2005/06/21 04:02:32 tgl Exp $
* $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.86 2005/06/26 03:03:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1692,7 +1692,7 @@ setup_privileges(void)
char **priv_lines;
static char *privileges_setup[] = {
"UPDATE pg_class "
" SET relacl = '{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
" SET relacl = E'{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
" WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;\n",
"GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n",
"GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n",
......@@ -1987,8 +1987,10 @@ escape_quotes(const char *src)
for (i = 0, j = 0; i < len; i++)
{
if (src[i] == '\'' || src[i] == '\\')
if (src[i] == '\\')
result[j++] = '\\';
if (src[i] == '\'') /* ANSI standard, '' */
result[j++] = '\'';
result[j++] = src[i];
}
result[j] = '\0';
......
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.61 2005/06/21 15:22:18 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.62 2005/06/26 03:03:48 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -538,7 +538,7 @@ dumpTablespaces(PGconn *conn)
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
"spclocation, spcacl "
"FROM pg_catalog.pg_tablespace "
"WHERE spcname NOT LIKE 'pg\\_%'");
"WHERE spcname NOT LIKE E'pg\\_%'");
if (PQntuples(res) > 0)
printf("--\n-- Tablespaces\n--\n\n");
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.117 2005/06/14 23:59:31 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.118 2005/06/26 03:03:56 momjian Exp $
*/
#include "postgres_fe.h"
#include "describe.h"
......@@ -1766,7 +1766,7 @@ listSchemas(const char *pattern, bool verbose)
appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_namespace n LEFT JOIN pg_catalog.pg_user u\n"
" ON n.nspowner=u.usesysid\n"
"WHERE (n.nspname NOT LIKE 'pg\\\\_temp\\\\_%%' OR\n"
"WHERE (n.nspname NOT LIKE E'pg\\\\_temp\\\\_%%' OR\n"
" n.nspname = (pg_catalog.current_schemas(true))[1])\n"); /* temp schema is first */
processNamePattern(&buf, pattern, true, false,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.370 2005/06/24 20:53:32 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.371 2005/06/26 03:04:01 momjian Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -1462,7 +1462,7 @@ DATA(insert OID = 1156 ( timestamptz_ge PGNSP PGUID 12 f f t f i 2 16 "1184 1
DESCR("greater-than-or-equal");
DATA(insert OID = 1157 ( timestamptz_gt PGNSP PGUID 12 f f t f i 2 16 "1184 1184" _null_ _null_ _null_ timestamp_gt - _null_ ));
DESCR("greater-than");
DATA(insert OID = 1158 ( to_timestamp PGNSP PGUID 14 f f t f i 1 1184 "701" _null_ _null_ _null_ "select (\'epoch\'::timestamptz + $1 * \'1 second\'::interval)" - _null_ ));
DATA(insert OID = 1158 ( to_timestamp PGNSP PGUID 14 f f t f i 1 1184 "701" _null_ _null_ _null_ "select (''epoch''::timestamptz + $1 * ''1 second''::interval)" - _null_ ));
DESCR("convert UNIX epoch to timestamptz");
DATA(insert OID = 1159 ( timezone PGNSP PGUID 12 f f t f i 2 1114 "25 1184" _null_ _null_ _null_ timestamptz_zone - _null_ ));
DESCR("adjust timestamp to new time zone");
......@@ -1542,7 +1542,7 @@ DESCR("adjust interval precision");
DATA(insert OID = 1215 ( obj_description PGNSP PGUID 14 f f t f s 2 25 "26 19" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 0" - _null_ ));
DESCR("get description for object id and catalog name");
DATA(insert OID = 1216 ( col_description PGNSP PGUID 14 f f t f s 2 25 "26 23" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = \'pg_catalog.pg_class\'::regclass and objsubid = $2" - _null_ ));
DATA(insert OID = 1216 ( col_description PGNSP PGUID 14 f f t f s 2 25 "26 23" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = ''pg_catalog.pg_class''::regclass and objsubid = $2" - _null_ ));
DESCR("get description for table column");
DATA(insert OID = 1217 ( date_trunc PGNSP PGUID 12 f f t f s 2 1184 "25 1184" _null_ _null_ _null_ timestamptz_trunc - _null_ ));
......@@ -2186,9 +2186,9 @@ DATA(insert OID = 877 ( substr PGNSP PGUID 12 f f t f i 3 25 "25 23 23" _nu
DESCR("return portion of string");
DATA(insert OID = 878 ( translate PGNSP PGUID 12 f f t f i 3 25 "25 25 25" _null_ _null_ _null_ translate - _null_ ));
DESCR("map a set of character appearing in string");
DATA(insert OID = 879 ( lpad PGNSP PGUID 14 f f t f i 2 25 "25 23" _null_ _null_ _null_ "select pg_catalog.lpad($1, $2, \' \')" - _null_ ));
DATA(insert OID = 879 ( lpad PGNSP PGUID 14 f f t f i 2 25 "25 23" _null_ _null_ _null_ "select pg_catalog.lpad($1, $2, '' '')" - _null_ ));
DESCR("left-pad string to length");
DATA(insert OID = 880 ( rpad PGNSP PGUID 14 f f t f i 2 25 "25 23" _null_ _null_ _null_ "select pg_catalog.rpad($1, $2, \' \')" - _null_ ));
DATA(insert OID = 880 ( rpad PGNSP PGUID 14 f f t f i 2 25 "25 23" _null_ _null_ _null_ "select pg_catalog.rpad($1, $2, '' '')" - _null_ ));
DESCR("right-pad string to length");
DATA(insert OID = 881 ( ltrim PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ ltrim1 - _null_ ));
DESCR("trim spaces from left end of string");
......
......@@ -7,7 +7,7 @@
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.60 2005/03/25 16:17:28 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.61 2005/06/26 03:04:12 momjian Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
......@@ -120,6 +120,7 @@ extern bool SQL_inheritance;
extern bool Australian_timezones;
extern bool default_with_oids;
extern bool escape_string_warning;
extern int log_min_error_statement;
extern int log_min_messages;
......
......@@ -436,7 +436,7 @@ select '{{1,{2}},{2,3}}'::text[];
ERROR: malformed array literal: "{{1,{2}},{2,3}}"
select '{{},{}}'::text[];
ERROR: malformed array literal: "{{},{}}"
select '{{1,2},\\{2,3}}'::text[];
select E'{{1,2},\\{2,3}}'::text[];
ERROR: malformed array literal: "{{1,2},\{2,3}}"
select '{{"1 2" x},{3}}'::text[];
ERROR: malformed array literal: "{{"1 2" x},{3}}"
......
......@@ -49,7 +49,7 @@ CONTEXT: COPY x, line 1: "2002 232 40 50 60 70 80"
-- various COPY options: delimiters, oids, NULL string
COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x';
COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
COPY x from stdin WITH DELIMITER AS ':' NULL AS '\\X';
COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X';
-- check results of copy in
SELECT * FROM x;
a | b | c | d | e
......@@ -176,8 +176,8 @@ CREATE TABLE y (
col1 text,
col2 text
);
INSERT INTO y VALUES ('Jackson, Sam', '\\h');
INSERT INTO y VALUES ('It is "perfect".','\t');
INSERT INTO y VALUES ('Jackson, Sam', E'\\h');
INSERT INTO y VALUES ('It is "perfect".',E'\t');
INSERT INTO y VALUES ('', NULL);
COPY y TO stdout WITH CSV;
"Jackson, Sam",\h
......@@ -187,7 +187,7 @@ COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|';
Jackson, Sam|\h
It is "perfect".|
''|
COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE '\\';
COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\';
"Jackson, Sam","\\h"
"It is \"perfect\"."," "
"",
......
......@@ -280,7 +280,7 @@ SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9'
| -4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
(5 rows)
SELECT '' AS to_char_16, to_char(q2, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
SELECT '' AS to_char_16, to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
to_char_16 | to_char
------------+-----------------------------------------------------------
| text 9999 "text between quote marks" 456
......
......@@ -1072,7 +1072,7 @@ SELECT '' AS to_char_19, to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9
| -2 4 9 2 6 8 0 4 . 0 4 5 0 4 7 4 2
(10 rows)
SELECT '' AS to_char_20, to_char(val, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data;
SELECT '' AS to_char_20, to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data;
to_char_20 | to_char
------------+-----------------------------------------------------------
| text 9999 "text between quote marks" 0
......
......@@ -25,7 +25,7 @@ select '(Joe,von Blow)'::fullname, '(Joe,d''Blow)'::fullname;
(Joe,"von Blow") | (Joe,d'Blow)
(1 row)
select '(Joe,"von""Blow")'::fullname, '(Joe,d\\\\Blow)'::fullname;
select '(Joe,"von""Blow")'::fullname, E'(Joe,d\\\\Blow)'::fullname;
fullname | fullname
-------------------+-----------------
(Joe,"von""Blow") | (Joe,"d\\Blow")
......
......@@ -1044,7 +1044,7 @@ SELECT '' AS to_char_5, to_char(d1, 'HH HH12 HH24 MI SS SSSS')
| 05 05 17 32 01 63121
(64 rows)
SELECT '' AS to_char_6, to_char(d1, '"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
SELECT '' AS to_char_6, to_char(d1, E'"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
FROM TIMESTAMP_TBL;
to_char_6 | to_char
-----------+-------------------------------------------------
......@@ -1358,7 +1358,7 @@ SELECT '' AS to_timestamp_5, to_timestamp('1,582nd VIII 21', 'Y,YYYth FMRM DD');
(1 row)
SELECT '' AS to_timestamp_6, to_timestamp('15 "text between quote marks" 98 54 45',
'HH "\\text between quote marks\\"" YY MI SS');
E'HH "\\text between quote marks\\"" YY MI SS');
to_timestamp_6 | to_timestamp
----------------+------------------------------
| Thu Jan 01 15:54:45 1998 PST
......
......@@ -1041,7 +1041,7 @@ SELECT '' AS to_char_5, to_char(d1, 'HH HH12 HH24 MI SS SSSS')
| 05 05 17 32 01 63121
(64 rows)
SELECT '' AS to_char_6, to_char(d1, '"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
SELECT '' AS to_char_6, to_char(d1, E'"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
FROM TIMESTAMPTZ_TBL;
to_char_6 | to_char
-----------+-------------------------------------------------
......@@ -1427,7 +1427,7 @@ SELECT '' AS to_timestamp_5, to_timestamp('1,582nd VIII 21', 'Y,YYYth FMRM DD');
(1 row)
SELECT '' AS to_timestamp_6, to_timestamp('15 "text between quote marks" 98 54 45',
'HH "\\text between quote marks\\"" YY MI SS');
E'HH "\\text between quote marks\\"" YY MI SS');
to_timestamp_6 | to_timestamp
----------------+------------------------------
| Thu Jan 01 15:54:45 1998 PST
......
......@@ -59,7 +59,7 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
-- NOTE: as of 8.0, this check finds smgr and unknown.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype in ('b') AND p1.typname NOT LIKE '\\_%' AND NOT EXISTS
WHERE p1.typtype in ('b') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
(SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid);
......
......@@ -62,10 +62,10 @@ create temp table copytest (
test text,
filler int);
insert into copytest values('DOS','abc\r\ndef',1);
insert into copytest values('Unix','abc\ndef',2);
insert into copytest values('Mac','abc\rdef',3);
insert into copytest values('esc\\ape','a\\r\\\r\\\n\\nb',4);
insert into copytest values('DOS',E'abc\r\ndef',1);
insert into copytest values('Unix',E'abc\ndef',2);
insert into copytest values('Mac',E'abc\rdef',3);
insert into copytest values(E'esc\\ape',E'a\\r\\\r\\\n\\nb',4);
copy copytest to '@abs_builddir@/results/copytest.csv' csv;
......@@ -79,9 +79,9 @@ truncate copytest2;
--- same test but with an escape char different from quote char
copy copytest to '@abs_builddir@/results/copytest.csv' csv quote '\'' escape '\\';
copy copytest to '@abs_builddir@/results/copytest.csv' csv quote '''' escape E'\\';
copy copytest2 from '@abs_builddir@/results/copytest.csv' csv quote '\'' escape '\\';
copy copytest2 from '@abs_builddir@/results/copytest.csv' csv quote '''' escape E'\\';
select * from copytest except select * from copytest2;
......
......@@ -37,10 +37,10 @@ create temp table copytest (
style text,
test text,
filler int);
insert into copytest values('DOS','abc\r\ndef',1);
insert into copytest values('Unix','abc\ndef',2);
insert into copytest values('Mac','abc\rdef',3);
insert into copytest values('esc\\ape','a\\r\\\r\\\n\\nb',4);
insert into copytest values('DOS',E'abc\r\ndef',1);
insert into copytest values('Unix',E'abc\ndef',2);
insert into copytest values('Mac',E'abc\rdef',3);
insert into copytest values(E'esc\\ape',E'a\\r\\\r\\\n\\nb',4);
copy copytest to '@abs_builddir@/results/copytest.csv' csv;
create temp table copytest2 (like copytest);
copy copytest2 from '@abs_builddir@/results/copytest.csv' csv;
......@@ -51,8 +51,8 @@ select * from copytest except select * from copytest2;
truncate copytest2;
--- same test but with an escape char different from quote char
copy copytest to '@abs_builddir@/results/copytest.csv' csv quote '\'' escape '\\';
copy copytest2 from '@abs_builddir@/results/copytest.csv' csv quote '\'' escape '\\';
copy copytest to '@abs_builddir@/results/copytest.csv' csv quote '''' escape E'\\';
copy copytest2 from '@abs_builddir@/results/copytest.csv' csv quote '''' escape E'\\';
select * from copytest except select * from copytest2;
style | test | filler
-------+------+--------
......
......@@ -204,7 +204,7 @@ select 'foo' ilike all (array['F%', '%O']); -- t
-- none of the following should be accepted
select '{{1,{2}},{2,3}}'::text[];
select '{{},{}}'::text[];
select '{{1,2},\\{2,3}}'::text[];
select E'{{1,2},\\{2,3}}'::text[];
select '{{"1 2" x},{3}}'::text[];
select '{}}'::text[];
select '{ }}'::text[];
......
......@@ -83,7 +83,7 @@ COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
3000;;c;;
\.
COPY x from stdin WITH DELIMITER AS ':' NULL AS '\\X';
COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X';
4000:\X:C:\X:\X
4001:1:empty::
4002:2:null:\X:\X
......@@ -121,13 +121,13 @@ CREATE TABLE y (
col2 text
);
INSERT INTO y VALUES ('Jackson, Sam', '\\h');
INSERT INTO y VALUES ('It is "perfect".','\t');
INSERT INTO y VALUES ('Jackson, Sam', E'\\h');
INSERT INTO y VALUES ('It is "perfect".',E'\t');
INSERT INTO y VALUES ('', NULL);
COPY y TO stdout WITH CSV;
COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|';
COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE '\\';
COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\';
--test that we read consecutive LFs properly
......
......@@ -61,5 +61,5 @@ SELECT '' AS to_char_12, to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL;
SELECT '' AS to_char_13, to_char(q2, 'L9999999999999999.000') FROM INT8_TBL;
SELECT '' AS to_char_14, to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL;
SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL;
SELECT '' AS to_char_16, to_char(q2, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
SELECT '' AS to_char_16, to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
SELECT '' AS to_char_17, to_char(q2, '999999SG9999999999') FROM INT8_TBL;
......@@ -742,7 +742,7 @@ SELECT '' AS to_char_16, to_char(val, 'L9999999999999999.099999999999999') FROM
SELECT '' AS to_char_17, to_char(val, 'FM9999999999999999.99999999999999') FROM num_data;
SELECT '' AS to_char_18, to_char(val, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data;
SELECT '' AS to_char_19, to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9') FROM num_data;
SELECT '' AS to_char_20, to_char(val, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data;
SELECT '' AS to_char_20, to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data;
SELECT '' AS to_char_21, to_char(val, '999999SG9999999999') FROM num_data;
SELECT '' AS to_char_22, to_char(val, 'FM9999999999999999.999999999999999') FROM num_data;
......
......@@ -20,7 +20,7 @@ select row('Joe', 'Blow')::fullname, '(Joe,Blow)'::fullname;
select '(Joe,von Blow)'::fullname, '(Joe,d''Blow)'::fullname;
select '(Joe,"von""Blow")'::fullname, '(Joe,d\\\\Blow)'::fullname;
select '(Joe,"von""Blow")'::fullname, E'(Joe,d\\\\Blow)'::fullname;
select '(Joe,"Blow,Jr")'::fullname;
......
......@@ -186,7 +186,7 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
SELECT '' AS to_char_5, to_char(d1, 'HH HH12 HH24 MI SS SSSS')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_6, to_char(d1, '"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
SELECT '' AS to_char_6, to_char(d1, E'"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_7, to_char(d1, 'HH24--text--MI--text--SS')
......@@ -211,7 +211,7 @@ SELECT '' AS to_timestamp_4, to_timestamp('My birthday-> Year: 1976, Month: May,
SELECT '' AS to_timestamp_5, to_timestamp('1,582nd VIII 21', 'Y,YYYth FMRM DD');
SELECT '' AS to_timestamp_6, to_timestamp('15 "text between quote marks" 98 54 45',
'HH "\\text between quote marks\\"" YY MI SS');
E'HH "\\text between quote marks\\"" YY MI SS');
SELECT '' AS to_timestamp_7, to_timestamp('05121445482000', 'MMDDHHMISSYYYY');
......
......@@ -179,7 +179,7 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
SELECT '' AS to_char_5, to_char(d1, 'HH HH12 HH24 MI SS SSSS')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_6, to_char(d1, '"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
SELECT '' AS to_char_6, to_char(d1, E'"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_7, to_char(d1, 'HH24--text--MI--text--SS')
......@@ -207,7 +207,7 @@ SELECT '' AS to_timestamp_4, to_timestamp('My birthday-> Year: 1976, Month: May,
SELECT '' AS to_timestamp_5, to_timestamp('1,582nd VIII 21', 'Y,YYYth FMRM DD');
SELECT '' AS to_timestamp_6, to_timestamp('15 "text between quote marks" 98 54 45',
'HH "\\text between quote marks\\"" YY MI SS');
E'HH "\\text between quote marks\\"" YY MI SS');
SELECT '' AS to_timestamp_7, to_timestamp('05121445482000', 'MMDDHHMISSYYYY');
......
......@@ -54,7 +54,7 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype in ('b') AND p1.typname NOT LIKE '\\_%' AND NOT EXISTS
WHERE p1.typtype in ('b') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
(SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册