Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vaiXm-00CSBc-0M for pgsql-hackers@arkaria.postgresql.org; Tue, 30 Dec 2025 22:50:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vaiXi-004iHC-3D for pgsql-hackers@arkaria.postgresql.org; Tue, 30 Dec 2025 22:50:19 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vaiXi-004iH4-1p for pgsql-hackers@lists.postgresql.org; Tue, 30 Dec 2025 22:50:19 +0000 Received: from sss.pgh.pa.us ([68.162.161.243]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vaiXf-003drl-1E for pgsql-hackers@lists.postgresql.org; Tue, 30 Dec 2025 22:50:18 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 5BUMoAgm3730916 for ; Tue, 30 Dec 2025 17:50:10 -0500 From: Tom Lane To: pgsql-hackers@lists.postgresql.org Subject: Re: Can we remove support for standard_conforming_strings = off yet? In-reply-to: <3279216.1767072538@sss.pgh.pa.us> References: <3279216.1767072538@sss.pgh.pa.us> Comments: In-reply-to Tom Lane message dated "Tue, 30 Dec 2025 00:28:58 -0500" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <3730908.1767135005.0@sss.pgh.pa.us> Date: Tue, 30 Dec 2025 17:50:10 -0500 Message-ID: <3730915.1767135010@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <3730908.1767135005.1@sss.pgh.pa.us> I wrote: > standard_conforming_strings has defaulted to ON since 2010 (see > 0839f312e in the 9.1 release). I propose that it's finally time to > force it on and get rid of code that supports the "off" setting. Here's a draft patch series for that. As I was working through it, I realized that there's one potentially-nasty point that might cause upgrading problems. To wit, pg_dump and pg_dumpall have historically replicated the source server's standard_conforming_strings setting into their output: they emit a SET command for that, and any string literals appearing in views or the like will be escaped accordingly. So if your old installation had standard_conforming_strings = off, and all you have from it is existing pg_dump output (either text or archive format), you are in a sticky situation because that dump will not restore cleanly. This isn't impossible to get out of, but you'd probably have to stand up a pre-v19 server, restore the dump into that, and take a fresh dump made with standard_conforming_strings = on. The alternative would be manual correction of literals in the dump script, which seems far too error-prone to be recommendable. This isn't a problem if you can make the dump with v19 pg_dump (and therefore it's not an issue for pg_upgrade cases). The attached patch series tweaks pg_dump to force standard_conforming_strings = on while dumping, so that it will produce a usable dump even if the source server had the wrong default. Nonetheless, if I thought there were more than epsilon existing installations still running standard_conforming_strings = off as a global setting, I'd worry that we still can't get away with making this change. But if I believed that, I wouldn't be proposing it. This observation does raise the stakes a bit though. Another comment worth making is that I oversold the code-savings benefit: > The code-removal aspect shouldn't be minimized either. There's > a nontrivial portion of scan.l that isn't reachable unless > standard_conforming_strings is off, and reducing the size of the > lexer probably translates directly to performance benefits. When I wrote that I was thinking we could get rid of the flex rules for the exclusive state, but of course we cannot: those rules are shared with the escape-string syntax E'...'. In the attached, the rules flex sees don't change at all. We can get rid of the code supporting escape_string_warning, because those warnings are unreachable unless standard_conforming_strings = off. But that's no large amount of code. I still think this is worth doing on the grounds of closing edge-case security holes. But perhaps it's not quite as attractive as I thought yesterday. A compromise position could be to apply only 0003 attached to change pg_dump[all]'s behavior, then wait a few more years so that the dump/reload hazard is minimized before we reconsider the main patch. Anyway, patches attached. regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name*0="v1-0001-Force-standard_conforming_strings-to-always-be-ON.p"; name*1="atch"; charset="us-ascii" Content-ID: <3730908.1767135005.2@sss.pgh.pa.us> Content-Description: v1-0001-Force-standard_conforming_strings-to-always-be-ON.patch Content-Transfer-Encoding: quoted-printable =46rom fca46f31942e973030b1ae2248e1d693bec249cb Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 30 Dec 2025 14:41:34 -0500 Subject: [PATCH v1 1/4] Force standard_conforming_strings to always be ON. Continuing to support this backwards-compatibility feature has nontrivial costs; in particular it is potentially a security hazard if an application somehow gets confused about which setting the server is using. We changed the default to ON fifteen years ago, which seems like enough time for applications to have adapted. Let's remove support for the legacy string syntax. We should not remove the GUC altogether, since client-side code will still test it, pg_dump scripts will attempt to set it to ON, etc. Instead, just prevent it from being set to OFF. There is precedent for this approach (see commit de66987ad). This initial patch locks down the setting to be ON, updates the documentation, and cleans up regression tests that now fail. Later patches will remove now-dead code and address some other loose ends such as what to do with escape_string_warning. Author: Tom Lane Discussion: https://postgr.es/m/3279216.1767072538@sss.pgh.pa.us --- contrib/pg_trgm/expected/pg_trgm.out | 3 - contrib/pg_trgm/sql/pg_trgm.sql | 4 - doc/src/sgml/config.sgml | 40 +++---- doc/src/sgml/ecpg.sgml | 4 +- doc/src/sgml/func/func-matching.sgml | 16 --- doc/src/sgml/hstore.sgml | 4 +- doc/src/sgml/libpq.sgml | 18 +-- doc/src/sgml/protocol.sgml | 3 +- doc/src/sgml/syntax.sgml | 35 ------ src/backend/commands/variable.c | 15 +++ src/backend/utils/misc/guc_parameters.dat | 8 +- src/backend/utils/misc/postgresql.conf.sample | 1 - src/include/utils/guc_hooks.h | 2 + src/interfaces/ecpg/test/expected/sql-quote.c | 90 ++++----------- .../ecpg/test/expected/sql-quote.stderr | 107 +++++------------- .../ecpg/test/expected/sql-quote.stdout | 3 - src/interfaces/ecpg/test/expected/sql-show.c | 2 +- .../ecpg/test/expected/sql-show.stderr | 4 +- .../ecpg/test/expected/sql-show.stdout | 2 +- src/interfaces/ecpg/test/sql/quote.pgc | 10 -- src/interfaces/ecpg/test/sql/show.pgc | 2 +- src/test/examples/testlibpq3.c | 1 - src/test/examples/testlibpq3.sql | 1 - .../test_regex/expected/test_regex.out | 1 - .../test_regex/expected/test_regex_utf8.out | 1 - .../modules/test_regex/sql/test_regex.sql | 2 - .../test_regex/sql/test_regex_utf8.sql | 2 - src/test/regress/expected/plpgsql.out | 45 -------- src/test/regress/expected/regex.out | 2 - src/test/regress/expected/strings.out | 94 +-------------- src/test/regress/sql/plpgsql.sql | 22 ---- src/test/regress/sql/regex.sql | 3 - src/test/regress/sql/strings.sql | 31 +---- src/tutorial/syscat.source | 7 +- 34 files changed, 112 insertions(+), 473 deletions(-) diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expect= ed/pg_trgm.out index 04da98170ab..612625f1fda 100644 --- a/contrib/pg_trgm/expected/pg_trgm.out +++ b/contrib/pg_trgm/expected/pg_trgm.out @@ -7,9 +7,6 @@ WHERE opc.oid >=3D 16384 AND NOT amvalidate(opc.oid); --------+--------- (0 rows) = ---backslash is used in tests below, installcheck will fail if ---standard_conforming_string is off -set standard_conforming_strings=3Don; -- reduce noise set extra_float_digits =3D 0; select show_trgm(''); diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm= .sql index 44debced6d5..49db86caf7d 100644 --- a/contrib/pg_trgm/sql/pg_trgm.sql +++ b/contrib/pg_trgm/sql/pg_trgm.sql @@ -5,10 +5,6 @@ SELECT amname, opcname FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid =3D opcmethod WHERE opc.oid >=3D 16384 AND NOT amvalidate(opc.oid); = ---backslash is used in tests below, installcheck will fail if ---standard_conforming_string is off -set standard_conforming_strings=3Don; - -- reduce noise set extra_float_digits =3D 0; = diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index cdfe8e376f0..9ca6b73aa8b 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -11388,8 +11388,9 @@ dynamic_library_path =3D '/usr/local/lib/postgresq= l:$libdir' - This controls whether a quote mark can be represented by - \' in a string literal. The preferred, SQL-st= andard way + This parameter controls whether a quote mark can be represented b= y + \' in the escape string syntax + (E'...'). The preferred, SQL-standard way to represent a quote mark is by doubling it ('') but PostgreSQL has historically also accep= ted \'. However, use of \' crea= tes security risks @@ -11408,10 +11409,9 @@ dynamic_library_path =3D '/usr/local/lib/postgres= ql:$libdir' = - Note that in a standard-conforming string literal, \ just - means \ anyway. This parameter only affects t= he handling of - non-standard-conforming literals, including - escape string syntax (E'...'). + Note that in an ordinary string literal, \ jus= t + means \ anyway. This parameter only affects + the handling of escape string syntax. @@ -11425,17 +11425,8 @@ dynamic_library_path =3D '/usr/local/lib/postgres= ql:$libdir' - When on, a warning is issued if a backslash (\= ) - appears in an ordinary string literal ('...' - syntax) and standard_conforming_strings is off= . - The default is on. - - - Applications that wish to use backslash as escape should be - modified to use escape string syntax (E'...'), - because the default behavior of ordinary strings is now to treat - backslash as an ordinary character, per SQL standard. This varia= ble - can be enabled to help locate code that needs to be changed. + This parameter no longer does anything, because + standard_conforming_strings cannot be turned o= ff. @@ -11491,15 +11482,12 @@ dynamic_library_path =3D '/usr/local/lib/postgre= sql:$libdir' - This controls whether ordinary string literals - ('...') treat backslashes literally, as specif= ied in - the SQL standard. - Beginning in PostgreSQL 9.1, the defau= lt is - on (prior releases defaulted to off). - Applications can 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 (E'...') is supp= orted. + Beginning in PostgreSQL 19, this + parameter is always on. String literals are + always parsed as specified in the SQL standard (that is, + backslashes are ordinary characters within a string literal). + This parameter continues to exist because applications may consul= t + it; but it cannot be set to off. Escape string syntax () should be used if an application desires backslashes to be treated as escape characters. diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index e6e3a82905c..6203b2518cf 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -75,9 +75,7 @@ EXEC SQL ...; Embedded SQL statements likewise use SQL rules, not C rules, for parsing quoted strings and identifiers. (See and - respectively. Note that - ECPG assumes that standard_conforming_strings - is on.) + respectively.) Of course, the C part of the program follows C quoting rules. = diff --git a/doc/src/sgml/func/func-matching.sgml b/doc/src/sgml/func/func= -matching.sgml index f466860ddb0..b159137f93a 100644 --- a/doc/src/sgml/func/func-matching.sgml +++ b/doc/src/sgml/func/func-matching.sgml @@ -152,14 +152,6 @@ character itself, write two escape characters. = - - - If you have turn= ed off, - any backslashes you write in literal string constants will need to b= e - doubled. See for more inform= ation. - - - It's also possible to select no escape character by writing ESCAPE ''. This effectively disables the @@ -1156,14 +1148,6 @@ regexp_substr('ABCDEFGHI', '(c..)(...)', 1, 1, 'i',= 2) An RE cannot end with a backslash (\). = - - - If you have turn= ed off, - any backslashes you write in literal string constants will need to b= e - doubled. See for more inform= ation. - - - Regular Expression Quantifiers = diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml index 5f8d1d1ff43..780ee224dce 100644 --- a/doc/src/sgml/hstore.sgml +++ b/doc/src/sgml/hstore.sgml @@ -73,9 +73,7 @@ key =3D> NULL applies before any required quoting or escaping. = If you are passing an hstore literal via a parameter, then no additi= onal processing is needed. But if you're passing it as a quoted literal - constant, then any single-quote characters and (depending on the setti= ng of - the standard_conforming_strings configuration param= eter) - backslash characters need to be escaped correctly. See + constant, then any single-quote characters need to be escaped correctl= y. See for more on the handling of str= ing constants. diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 7d05938feda..88d2a5f96c9 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -2889,18 +2889,13 @@ const char *PQparameterStatus(const PGconn *conn, = const char *paramName); before 16; search_path was not reported by rele= ases before 18.) Note that - server_version, - server_encoding and - integer_datetimes + server_version and + server_encoding cannot change after startup. - - - - If no value for standard_conforming_strings is = reported, - applications can assume it is off, that is, bac= kslashes - are treated as escapes in string literals. Also, the presence of - this parameter can be taken as an indication that the escape strin= g - syntax (E'...') is accepted. + Also, integer_datetimes is + always on in releases 9.5 and later, + and standard_conforming_strings is + always on in releases 19 and later. = @@ -11108,7 +11103,6 @@ main(int argc, char **argv) * * CREATE SCHEMA testlibpq3; * SET search_path =3D testlibpq3; - * SET standard_conforming_strings =3D ON; * CREATE TABLE test1 (i int4, t text, b bytea); * INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004'); * INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000'); diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 41c5954a424..a2b528c481e 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -3040,8 +3040,7 @@ psql "dbname=3Dpostgres replication=3Ddatabase" -c "= IDENTIFY_SYSTEM;" Sets the label of the backup. If none is specified, a backup l= abel of base backup will be used. The quoting ru= les - for the label are the same as a standard SQL string with - turned on. + for the label are the same as for a standard SQL string. diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml index 34c83880a66..67482996861 100644 --- a/doc/src/sgml/syntax.sgml +++ b/doc/src/sgml/syntax.sgml @@ -438,30 +438,6 @@ SELECT 'foo' 'bar'; will check that the character conversion is possible. = - - - If the configuration parameter - is off<= /literal>, - then PostgreSQL recognizes backslash esca= pes - in both regular and escape string constants. However, as of - PostgreSQL 9.1, the default is o= n, meaning - that backslash escapes are recognized only in escape string constant= s. - This behavior is more standards-compliant, but might break applicati= ons - which rely on the historical behavior, where backslash escapes - were always recognized. As a workaround, you can set this parameter - to off, but it is better to migrate away from usi= ng backslash - escapes. If you need to use a backslash escape to represent a speci= al - character, write the string constant with an E. - - - - In addition to standard_conforming_strings, the c= onfiguration - parameters and - govern treatment of backslas= hes - in string constants. - - - The character with the code zero cannot be in a string constant. @@ -532,17 +508,6 @@ U&'d!0061t!+000061' UESCAPE '!' by one of these escape sequences is converted to the actual server encoding; an error is reported if that's not possible. - - - Also, the Unicode escape syntax for string constants only works - when the configuration - parameter is - turned on. This is because otherwise this syntax could confuse - clients that parse the SQL statements to the point that it could - lead to SQL injections and similar security issues. If the - parameter is set to off, this syntax will be rejected with an - error message. - = diff --git a/src/backend/commands/variable.c b/src/backend/commands/variab= le.c index 608f10d9412..462bd9d2265 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -1257,3 +1257,18 @@ check_ssl(bool *newval, void **extra, GucSource sou= rce) #endif return true; } + +bool +check_standard_conforming_strings(bool *newval, void **extra, GucSource s= ource) +{ + if (!*newval) + { + /* check the GUC's definition for an explanation */ + GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED); + GUC_check_errmsg("non-standard string literals are not supported"); + + return false; + } + + return true; +} diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils= /misc/guc_parameters.dat index ac0c7c36c56..7f23186506a 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -2759,11 +2759,15 @@ boot_val =3D> '""', }, = +# We removed support for non-conforming string literals in PostgreSQL 19, +# but this parameter must be kept indefinitely, since client code might +# consult it or attempt to set it. We allow it to be explicitly set to t= rue. { name =3D> 'standard_conforming_strings', type =3D> 'bool', context =3D>= 'PGC_USERSET', group =3D> 'COMPAT_OPTIONS_PREVIOUS', - short_desc =3D> 'Causes \'...\' strings to treat backslashes literally.= ', - flags =3D> 'GUC_REPORT', + short_desc =3D> 'Nonstandard strings are no longer supported; this can = only be true.', + flags =3D> 'GUC_REPORT | GUC_NOT_IN_SAMPLE', variable =3D> 'standard_conforming_strings', boot_val =3D> 'true', + check_hook =3D> 'check_standard_conforming_strings', }, = { name =3D> 'statement_timeout', type =3D> 'int', context =3D> 'PGC_USERS= ET', group =3D> 'CLIENT_CONN_STATEMENT', diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/u= tils/misc/postgresql.conf.sample index dc9e2255f8a..ec356f62ad1 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -850,7 +850,6 @@ #escape_string_warning =3D on #lo_compat_privileges =3D off #quote_all_identifiers =3D off -#standard_conforming_strings =3D on #synchronize_seqscans =3D on = # - Other Platforms and Clients - diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h index fbe0b1e2e3d..41a32dcd263 100644 --- a/src/include/utils/guc_hooks.h +++ b/src/include/utils/guc_hooks.h @@ -134,6 +134,8 @@ extern void assign_session_replication_role(int newval= , void *extra); extern void assign_stats_fetch_consistency(int newval, void *extra); extern bool check_ssl(bool *newval, void **extra, GucSource source); extern bool check_stage_log_stats(bool *newval, void **extra, GucSource s= ource); +extern bool check_standard_conforming_strings(bool *newval, void **extra, + GucSource source); extern bool check_subtrans_buffers(int *newval, void **extra, GucSource source); extern bool check_synchronous_standby_names(char **newval, void **extra, diff --git a/src/interfaces/ecpg/test/expected/sql-quote.c b/src/interface= s/ecpg/test/expected/sql-quote.c index 05841bd6999..ddc1e90b1c3 100644 --- a/src/interfaces/ecpg/test/expected/sql-quote.c +++ b/src/interfaces/ecpg/test/expected/sql-quote.c @@ -61,7 +61,7 @@ if (sqlca.sqlcode < 0) exit (1);} #line 20 "quote.pgc" = = - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set standard_conformi= ng_strings to off", ECPGt_EOIT, ECPGt_EORT); + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set standard_conformi= ng_strings to on", ECPGt_EOIT, ECPGt_EORT); #line 22 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); @@ -84,8 +84,8 @@ if (sqlca.sqlcode < 0) exit (1);} = printf("Standard conforming strings: %s\n", var); = - /* this is a\\b actually */ - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into \"My_Tabl= e\" values ( 1 , 'a\\\\\\\\b' )", ECPGt_EOIT, ECPGt_EORT); + /* this is a\\\\b actually */ + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into \"My_Tabl= e\" values ( 2 , 'a\\\\\\\\b' )", ECPGt_EOIT, ECPGt_EORT); #line 28 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); @@ -95,7 +95,7 @@ if (sqlca.sqlcode < 0) exit (1);} #line 28 "quote.pgc" = /* this is a\\b */ - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into \"My_Tabl= e\" values ( 1 , E'a\\\\\\\\b' )", ECPGt_EOIT, ECPGt_EORT); + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into \"My_Tabl= e\" values ( 2 , E'a\\\\\\\\b' )", ECPGt_EOIT, ECPGt_EORT); #line 30 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); @@ -105,7 +105,7 @@ if (sqlca.sqlcode < 0) exit (1);} #line 30 "quote.pgc" = = - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set standard_conformi= ng_strings to on", ECPGt_EOIT, ECPGt_EORT); + { ECPGtrans(__LINE__, NULL, "begin"); #line 32 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); @@ -114,66 +114,22 @@ if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); if (sqlca.sqlcode < 0) exit (1);} #line 32 "quote.pgc" = - - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "show standard_conform= ing_strings", ECPGt_EOIT, = - ECPGt_char,(var),(long)25,(long)1,(25)*sizeof(char), = - ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 34 "quote.pgc" - -if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 34 "quote.pgc" - -if (sqlca.sqlcode < 0) exit (1);} -#line 34 "quote.pgc" - - printf("Standard conforming strings: %s\n", var); - - /* this is a\\\\b actually */ - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into \"My_Tabl= e\" values ( 2 , 'a\\\\\\\\b' )", ECPGt_EOIT, ECPGt_EORT); -#line 38 "quote.pgc" - -if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 38 "quote.pgc" - -if (sqlca.sqlcode < 0) exit (1);} -#line 38 "quote.pgc" - - /* this is a\\b */ - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into \"My_Tabl= e\" values ( 2 , E'a\\\\\\\\b' )", ECPGt_EOIT, ECPGt_EORT); -#line 40 "quote.pgc" - -if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 40 "quote.pgc" - -if (sqlca.sqlcode < 0) exit (1);} -#line 40 "quote.pgc" - - - { ECPGtrans(__LINE__, NULL, "begin"); -#line 42 "quote.pgc" - -if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 42 "quote.pgc" - -if (sqlca.sqlcode < 0) exit (1);} -#line 42 "quote.pgc" - /* declare C cursor for select * from \"My_Table\" */ -#line 43 "quote.pgc" +#line 33 "quote.pgc" = = { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare C cursor for = select * from \"My_Table\"", ECPGt_EOIT, ECPGt_EORT); -#line 45 "quote.pgc" +#line 35 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 45 "quote.pgc" +#line 35 "quote.pgc" = if (sqlca.sqlcode < 0) exit (1);} -#line 45 "quote.pgc" +#line 35 "quote.pgc" = = /* exec sql whenever not found break ; */ -#line 47 "quote.pgc" +#line 37 "quote.pgc" = = for (loopcount =3D 0; loopcount < 100; loopcount++) @@ -183,47 +139,47 @@ if (sqlca.sqlcode < 0) exit (1);} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, = ECPGt_char,(var),(long)25,(long)1,(25)*sizeof(char), = ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 51 "quote.pgc" +#line 41 "quote.pgc" = if (sqlca.sqlcode =3D=3D ECPG_NOT_FOUND) break; -#line 51 "quote.pgc" +#line 41 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 51 "quote.pgc" +#line 41 "quote.pgc" = if (sqlca.sqlcode < 0) exit (1);} -#line 51 "quote.pgc" +#line 41 "quote.pgc" = printf("value: %d %s\n", i, var); } = { ECPGtrans(__LINE__, NULL, "rollback"); -#line 55 "quote.pgc" +#line 45 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 55 "quote.pgc" +#line 45 "quote.pgc" = if (sqlca.sqlcode < 0) exit (1);} -#line 55 "quote.pgc" +#line 45 "quote.pgc" = { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table \"My_Table= \"", ECPGt_EOIT, ECPGt_EORT); -#line 56 "quote.pgc" +#line 46 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 56 "quote.pgc" +#line 46 "quote.pgc" = if (sqlca.sqlcode < 0) exit (1);} -#line 56 "quote.pgc" +#line 46 "quote.pgc" = = { ECPGdisconnect(__LINE__, "ALL"); -#line 58 "quote.pgc" +#line 48 "quote.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); -#line 58 "quote.pgc" +#line 48 "quote.pgc" = if (sqlca.sqlcode < 0) exit (1);} -#line 58 "quote.pgc" +#line 48 "quote.pgc" = = return 0; diff --git a/src/interfaces/ecpg/test/expected/sql-quote.stderr b/src/inte= rfaces/ecpg/test/expected/sql-quote.stderr index 3df8702a8a6..5f5bfb8133a 100644 --- a/src/interfaces/ecpg/test/expected/sql-quote.stderr +++ b/src/interfaces/ecpg/test/expected/sql-quote.stderr @@ -10,7 +10,7 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 20: OK: CREATE TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 22: query: set standard_conforming_strings= to off; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 22: query: set standard_conforming_strings= to on; with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 22: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 @@ -22,114 +22,63 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 24: correctly got 1 tuples with 1 f= ields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 24: RESULT: off offset: -1; array: no +[NO_PID]: ecpg_get_data on line 24: RESULT: on offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 28: query: insert into "My_Table" values (= 1 , 'a\\\\b' ); with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 28: query: insert into "My_Table" values (= 2 , 'a\\\\b' ); with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGnoticeReceiver: nonstandard use of \\ in a string literal -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: raising sqlcode 0 -[NO_PID]: sqlca: code: 0, state: 22P06 [NO_PID]: ecpg_execute on line 28: using PQexec -[NO_PID]: sqlca: code: 0, state: 22P06 +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 28: OK: INSERT 0 1 -[NO_PID]: sqlca: code: 0, state: 22P06 -SQL error: nonstandard use of \\ in a string literal -[NO_PID]: ecpg_execute on line 30: query: insert into "My_Table" values (= 1 , E'a\\\\b' ); with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 30: query: insert into "My_Table" values (= 2 , E'a\\\\b' ); with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 30: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 30: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 32: query: set standard_conforming_strings= to on; with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 32: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 32: OK: SET -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 34: query: show standard_conforming_string= s; with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 34: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 34: correctly got 1 tuples with 1 f= ields -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 34: RESULT: on offset: -1; array: no -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 38: query: insert into "My_Table" values (= 2 , 'a\\\\b' ); with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 38: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 38: OK: INSERT 0 1 -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 40: query: insert into "My_Table" values (= 2 , E'a\\\\b' ); with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 40: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 40: OK: INSERT 0 1 -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 42: action "begin"; connection "ecpg1_regress= ion" -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 45: query: declare C cursor for select * f= rom "My_Table"; with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 45: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 45: OK: DECLARE CURSOR -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 51: correctly got 1 tuples with 2 f= ields -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: 1 offset: -1; array: no -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: a\\b offset: -1; array: no -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: using PQexec +[NO_PID]: ECPGtrans on line 32: action "begin"; connection "ecpg1_regress= ion" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 51: correctly got 1 tuples with 2 f= ields +[NO_PID]: ecpg_execute on line 35: query: declare C cursor for select * f= rom "My_Table"; with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: 1 offset: -1; array: no +[NO_PID]: ecpg_execute on line 35: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: a\\b offset: -1; array: no +[NO_PID]: ecpg_process_output on line 35: OK: DECLARE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression +[NO_PID]: ecpg_execute on line 41: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: using PQexec +[NO_PID]: ecpg_execute on line 41: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 51: correctly got 1 tuples with 2 f= ields +[NO_PID]: ecpg_process_output on line 41: correctly got 1 tuples with 2 f= ields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: 2 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 41: RESULT: 2 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: a\\\\b offset: -1; array: no +[NO_PID]: ecpg_get_data on line 41: RESULT: a\\\\b offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression +[NO_PID]: ecpg_execute on line 41: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: using PQexec +[NO_PID]: ecpg_execute on line 41: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 51: correctly got 1 tuples with 2 f= ields +[NO_PID]: ecpg_process_output on line 41: correctly got 1 tuples with 2 f= ields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: 2 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 41: RESULT: 2 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 51: RESULT: a\\b offset: -1; array: no +[NO_PID]: ecpg_get_data on line 41: RESULT: a\\b offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression +[NO_PID]: ecpg_execute on line 41: query: fetch C; with 0 parameter(s) on= connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 51: using PQexec +[NO_PID]: ecpg_execute on line 41: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 51: correctly got 0 tuples with 2 f= ields +[NO_PID]: ecpg_process_output on line 41: correctly got 0 tuples with 2 f= ields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: raising sqlcode 100 on line 51: no data found on line 51 +[NO_PID]: raising sqlcode 100 on line 41: no data found on line 41 [NO_PID]: sqlca: code: 100, state: 02000 -[NO_PID]: ECPGtrans on line 55: action "rollback"; connection "ecpg1_regr= ession" +[NO_PID]: ECPGtrans on line 45: action "rollback"; connection "ecpg1_regr= ession" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 56: query: drop table "My_Table"; with 0 p= arameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 46: query: drop table "My_Table"; with 0 p= arameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 56: using PQexec +[NO_PID]: ecpg_execute on line 46: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 56: OK: DROP TABLE +[NO_PID]: ecpg_process_output on line 46: OK: DROP TABLE [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection ecpg1_regression closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-quote.stdout b/src/inte= rfaces/ecpg/test/expected/sql-quote.stdout index 2f92f994831..31892d5261e 100644 --- a/src/interfaces/ecpg/test/expected/sql-quote.stdout +++ b/src/interfaces/ecpg/test/expected/sql-quote.stdout @@ -1,6 +1,3 @@ -Standard conforming strings: off Standard conforming strings: on -value: 1 a\\b -value: 1 a\\b value: 2 a\\\\b value: 2 a\\b diff --git a/src/interfaces/ecpg/test/expected/sql-show.c b/src/interfaces= /ecpg/test/expected/sql-show.c index 1b52d5eaf4e..f934dc99feb 100644 --- a/src/interfaces/ecpg/test/expected/sql-show.c +++ b/src/interfaces/ecpg/test/expected/sql-show.c @@ -90,7 +90,7 @@ if (sqlca.sqlcode < 0) sqlprint();} = printf("Var: Search path: %s\n", var); = - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set standard_conformi= ng_strings to off", ECPGt_EOIT, ECPGt_EORT); + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set standard_conformi= ng_strings to on", ECPGt_EOIT, ECPGt_EORT); #line 26 "show.pgc" = if (sqlca.sqlwarn[0] =3D=3D 'W') sqlprint(); diff --git a/src/interfaces/ecpg/test/expected/sql-show.stderr b/src/inter= faces/ecpg/test/expected/sql-show.stderr index c303a845b25..e906abad91e 100644 --- a/src/interfaces/ecpg/test/expected/sql-show.stderr +++ b/src/interfaces/ecpg/test/expected/sql-show.stderr @@ -30,7 +30,7 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_get_data on line 23: RESULT: public offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 26: query: set standard_conforming_strings= to off; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 26: query: set standard_conforming_strings= to on; with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 26: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 @@ -42,7 +42,7 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 27: correctly got 1 tuples with 1 f= ields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 27: RESULT: off offset: -1; array: no +[NO_PID]: ecpg_get_data on line 27: RESULT: on offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 30: query: set time zone PST8PDT; with 0 p= arameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-show.stdout b/src/inter= faces/ecpg/test/expected/sql-show.stdout index 9319c5d1135..d5628025a0e 100644 --- a/src/interfaces/ecpg/test/expected/sql-show.stdout +++ b/src/interfaces/ecpg/test/expected/sql-show.stdout @@ -1,5 +1,5 @@ Var: Search path: public Var: Search path: public -Var: Standard conforming strings: off +Var: Standard conforming strings: on Time Zone: PST8PDT Transaction isolation level: read committed diff --git a/src/interfaces/ecpg/test/sql/quote.pgc b/src/interfaces/ecpg/= test/sql/quote.pgc index 9b62b7da90d..5cf4833d053 100644 --- a/src/interfaces/ecpg/test/sql/quote.pgc +++ b/src/interfaces/ecpg/test/sql/quote.pgc @@ -19,16 +19,6 @@ int main() { = EXEC SQL CREATE TABLE "My_Table" ( Item1 int, Item2 text ); = - EXEC SQL SET standard_conforming_strings TO off; - - EXEC SQL SHOW standard_conforming_strings INTO :var; - printf("Standard conforming strings: %s\n", var); - - /* this is a\\b actually */ - EXEC SQL INSERT INTO "My_Table" VALUES ( 1, 'a\\\\b' ); - /* this is a\\b */ - EXEC SQL INSERT INTO "My_Table" VALUES ( 1, E'a\\\\b' ); - EXEC SQL SET standard_conforming_strings TO on; = EXEC SQL SHOW standard_conforming_strings INTO :var; diff --git a/src/interfaces/ecpg/test/sql/show.pgc b/src/interfaces/ecpg/t= est/sql/show.pgc index 339678ae994..232b3e77348 100644 --- a/src/interfaces/ecpg/test/sql/show.pgc +++ b/src/interfaces/ecpg/test/sql/show.pgc @@ -23,7 +23,7 @@ int main() { EXEC SQL SHOW search_path INTO :var; printf("Var: Search path: %s\n", var); = - EXEC SQL SET standard_conforming_strings TO off; + EXEC SQL SET standard_conforming_strings TO on; EXEC SQL SHOW standard_conforming_strings INTO :var; printf("Var: Standard conforming strings: %s\n", var); = diff --git a/src/test/examples/testlibpq3.c b/src/test/examples/testlibpq3= .c index 4f7b7913889..cf74865ccb9 100644 --- a/src/test/examples/testlibpq3.c +++ b/src/test/examples/testlibpq3.c @@ -10,7 +10,6 @@ * * CREATE SCHEMA testlibpq3; * SET search_path =3D testlibpq3; - * SET standard_conforming_strings =3D ON; * CREATE TABLE test1 (i int4, t text, b bytea); * INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004'); * INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000'); diff --git a/src/test/examples/testlibpq3.sql b/src/test/examples/testlibp= q3.sql index 35a95ca347b..a113849b14b 100644 --- a/src/test/examples/testlibpq3.sql +++ b/src/test/examples/testlibpq3.sql @@ -1,6 +1,5 @@ CREATE SCHEMA testlibpq3; SET search_path =3D testlibpq3; -SET standard_conforming_strings =3D ON; CREATE TABLE test1 (i int4, t text, b bytea); INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004'); INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000'); diff --git a/src/test/modules/test_regex/expected/test_regex.out b/src/tes= t/modules/test_regex/expected/test_regex.out index c44c717edf4..a3d35fc142c 100644 --- a/src/test/modules/test_regex/expected/test_regex.out +++ b/src/test/modules/test_regex/expected/test_regex.out @@ -5,7 +5,6 @@ -- Most commented lines below are copied from reg.test. Each -- test case is followed by an equivalent test using test_regex(). create extension test_regex; -set standard_conforming_strings =3D on; -- # support functions and preliminary misc. -- # This is sensitive to changes in message wording, but we really have = to -- # test the code->message expansion at least once. diff --git a/src/test/modules/test_regex/expected/test_regex_utf8.out b/sr= c/test/modules/test_regex/expected/test_regex_utf8.out index befd75e96f3..329780ef400 100644 --- a/src/test/modules/test_regex/expected/test_regex_utf8.out +++ b/src/test/modules/test_regex/expected/test_regex_utf8.out @@ -8,7 +8,6 @@ SELECT getdatabaseencoding() <> 'UTF8' \quit \endif set client_encoding =3D utf8; -set standard_conforming_strings =3D on; -- Run the Tcl test cases that require Unicode -- expectMatch 9.44 EMP* {a[\u00fe-\u0507][\u00ff-\u0300]b} \ -- "a\u0102\u02ffb" "a\u0102\u02ffb" diff --git a/src/test/modules/test_regex/sql/test_regex.sql b/src/test/mod= ules/test_regex/sql/test_regex.sql index b2a847577e8..8f80ce0fe1d 100644 --- a/src/test/modules/test_regex/sql/test_regex.sql +++ b/src/test/modules/test_regex/sql/test_regex.sql @@ -7,8 +7,6 @@ = create extension test_regex; = -set standard_conforming_strings =3D on; - -- # support functions and preliminary misc. -- # This is sensitive to changes in message wording, but we really have = to -- # test the code->message expansion at least once. diff --git a/src/test/modules/test_regex/sql/test_regex_utf8.sql b/src/tes= t/modules/test_regex/sql/test_regex_utf8.sql index 2aa3e0f1022..1f69f105fd7 100644 --- a/src/test/modules/test_regex/sql/test_regex_utf8.sql +++ b/src/test/modules/test_regex/sql/test_regex_utf8.sql @@ -11,8 +11,6 @@ SELECT getdatabaseencoding() <> 'UTF8' = set client_encoding =3D utf8; = -set standard_conforming_strings =3D on; - = -- Run the Tcl test cases that require Unicode = diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expe= cted/plpgsql.out index 474be478ce8..b37b2abaf80 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -4576,51 +4576,6 @@ CONTEXT: PL/pgSQL expression "1/0" PL/pgSQL function fail() line 3 at RETURN drop function fail(); -- Test handling of string literals. -set standard_conforming_strings =3D off; -create or replace function strtest() returns text as $$ -begin - raise notice 'foo\\bar\041baz'; - return 'foo\\bar\041baz'; -end -$$ language plpgsql; -WARNING: nonstandard use of \\ in a string literal -LINE 3: raise notice 'foo\\bar\041baz'; - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 4: return 'foo\\bar\041baz'; - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 4: return 'foo\\bar\041baz'; - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -select strtest(); -NOTICE: foo\bar!baz -WARNING: nonstandard use of \\ in a string literal -LINE 1: 'foo\\bar\041baz' - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -QUERY: 'foo\\bar\041baz' - strtest = -------------- - foo\bar!baz -(1 row) - -create or replace function strtest() returns text as $$ -begin - raise notice E'foo\\bar\041baz'; - return E'foo\\bar\041baz'; -end -$$ language plpgsql; -select strtest(); -NOTICE: foo\bar!baz - strtest = -------------- - foo\bar!baz -(1 row) - -set standard_conforming_strings =3D on; create or replace function strtest() returns text as $$ begin raise notice 'foo\\bar\041baz\'; diff --git a/src/test/regress/expected/regex.out b/src/test/regress/expect= ed/regex.out index ae0de7307db..9fd503ffe78 100644 --- a/src/test/regress/expected/regex.out +++ b/src/test/regress/expected/regex.out @@ -1,8 +1,6 @@ -- -- Regular expression tests -- --- Don't want to have to double backslashes in regexes -set standard_conforming_strings =3D on; -- Test simple quantified backrefs select 'bbbbb' ~ '^([bc])\1*$' as t; t = diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expe= cted/strings.out index 727304f60e7..6eb92bc8442 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -22,7 +22,6 @@ ERROR: syntax error at or near "' - third line'" LINE 3: ' - third line' ^ -- Unicode escapes -SET standard_conforming_strings TO on; SELECT U&'d\0061t\+000061' AS U&"d\0061t\+000061"; data = ------ @@ -142,43 +141,12 @@ SELECT E'wrong: \U002FFFFF'; ERROR: invalid Unicode escape value at or near "\U002FFFFF" LINE 1: SELECT E'wrong: \U002FFFFF'; ^ +-- this is no longer allowed: SET standard_conforming_strings TO off; -SELECT U&'d\0061t\+000061' AS U&"d\0061t\+000061"; -ERROR: unsafe use of string constant with Unicode escapes -LINE 1: SELECT U&'d\0061t\+000061' AS U&"d\0061t\+000061"; - ^ -DETAIL: String constants with Unicode escapes cannot be used when "stand= ard_conforming_strings" is off. -SELECT U&'d!0061t\+000061' UESCAPE '!' AS U&"d*0061t\+000061" UESCAPE '*'= ; -ERROR: unsafe use of string constant with Unicode escapes -LINE 1: SELECT U&'d!0061t\+000061' UESCAPE '!' AS U&"d*0061t\+000061... - ^ -DETAIL: String constants with Unicode escapes cannot be used when "stand= ard_conforming_strings" is off. -SELECT U&' \' UESCAPE '!' AS "tricky"; -ERROR: unsafe use of string constant with Unicode escapes -LINE 1: SELECT U&' \' UESCAPE '!' AS "tricky"; - ^ -DETAIL: String constants with Unicode escapes cannot be used when "stand= ard_conforming_strings" is off. -SELECT 'tricky' AS U&"\" UESCAPE '!'; - \ = --------- - tricky -(1 row) - -SELECT U&'wrong: \061'; -ERROR: unsafe use of string constant with Unicode escapes -LINE 1: SELECT U&'wrong: \061'; - ^ -DETAIL: String constants with Unicode escapes cannot be used when "stand= ard_conforming_strings" is off. -SELECT U&'wrong: \+0061'; -ERROR: unsafe use of string constant with Unicode escapes -LINE 1: SELECT U&'wrong: \+0061'; - ^ -DETAIL: String constants with Unicode escapes cannot be used when "stand= ard_conforming_strings" is off. -SELECT U&'wrong: +0061' UESCAPE '+'; -ERROR: unsafe use of string constant with Unicode escapes -LINE 1: SELECT U&'wrong: +0061' UESCAPE '+'; - ^ -DETAIL: String constants with Unicode escapes cannot be used when "stand= ard_conforming_strings" is off. +ERROR: non-standard string literals are not supported +-- but this should be acceptable: +SET standard_conforming_strings TO on; +-- or this: RESET standard_conforming_strings; -- bytea SET bytea_output TO hex; @@ -2872,20 +2840,6 @@ SELECT '\x8000000000000000'::bytea::int8 AS "-92233= 72036854775808", -- -- test behavior of escape_string_warning and standard_conforming_strings= options -- -set escape_string_warning =3D off; -set standard_conforming_strings =3D 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 =3D on; set standard_conforming_strings =3D on; show escape_string_warning; @@ -2906,37 +2860,6 @@ select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' = as f3, 'abcd\' as f4, 'ab\' a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\ (1 row) = -set standard_conforming_strings =3D off; -select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' a= s f4, 'ab\\\'cd' as f5, '\\\\' as f6; -WARNING: nonstandard use of \\ in a string literal -LINE 1: select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3,... - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 1: select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3,... - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 1: select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3,... - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 1: ...bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' ..= . - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 1: ...'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd'..= . - ^ -HINT: Use the escape string syntax for backslashes, e.g., E'\\'. -WARNING: nonstandard use of \\ in a string literal -LINE 1: ...'''cd' as f3, 'abcd\\' as f4, 'ab\\\'cd' as f5, '\\\\' as ..= . - ^ -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 =3D off; set standard_conforming_strings =3D 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; @@ -2945,13 +2868,6 @@ select 'a\bcd' as f1, 'a\b''cd' as f2, 'a\b''''cd' = as f3, 'abcd\' as f4, 'ab\' a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\ (1 row) = -set standard_conforming_strings =3D off; -select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' a= s 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) - reset standard_conforming_strings; -- -- Additional string functions diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgs= ql.sql index d413d995d17..ae6b67e3e22 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -3773,28 +3773,6 @@ drop function fail(); = -- Test handling of string literals. = -set standard_conforming_strings =3D off; - -create or replace function strtest() returns text as $$ -begin - raise notice 'foo\\bar\041baz'; - return 'foo\\bar\041baz'; -end -$$ language plpgsql; - -select strtest(); - -create or replace function strtest() returns text as $$ -begin - raise notice E'foo\\bar\041baz'; - return E'foo\\bar\041baz'; -end -$$ language plpgsql; - -select strtest(); - -set standard_conforming_strings =3D on; - create or replace function strtest() returns text as $$ begin raise notice 'foo\\bar\041baz\'; diff --git a/src/test/regress/sql/regex.sql b/src/test/regress/sql/regex.s= ql index 56217104ce6..a4f99c1f25f 100644 --- a/src/test/regress/sql/regex.sql +++ b/src/test/regress/sql/regex.sql @@ -2,9 +2,6 @@ -- Regular expression tests -- = --- Don't want to have to double backslashes in regexes -set standard_conforming_strings =3D on; - -- Test simple quantified backrefs select 'bbbbb' ~ '^([bc])\1*$' as t; select 'ccc' ~ '^([bc])\1*$' as t; diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strin= gs.sql index 88aa4c2983b..531d409542f 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -17,8 +17,6 @@ SELECT 'first line' AS "Illegal comment within continuation"; = -- Unicode escapes -SET standard_conforming_strings TO on; - SELECT U&'d\0061t\+000061' AS U&"d\0061t\+000061"; SELECT U&'d!0061t\+000061' UESCAPE '!' AS U&"d*0061t\+000061" UESCAPE '*'= ; SELECT U&'a\\b' AS "a\b"; @@ -50,18 +48,11 @@ SELECT E'wrong: \udb99\u0061'; SELECT E'wrong: \U0000db99\U00000061'; SELECT E'wrong: \U002FFFFF'; = +-- this is no longer allowed: SET standard_conforming_strings TO off; - -SELECT U&'d\0061t\+000061' AS U&"d\0061t\+000061"; -SELECT U&'d!0061t\+000061' UESCAPE '!' AS U&"d*0061t\+000061" UESCAPE '*'= ; - -SELECT U&' \' UESCAPE '!' AS "tricky"; -SELECT 'tricky' AS U&"\" UESCAPE '!'; - -SELECT U&'wrong: \061'; -SELECT U&'wrong: \+0061'; -SELECT U&'wrong: +0061' UESCAPE '+'; - +-- but this should be acceptable: +SET standard_conforming_strings TO on; +-- or this: RESET standard_conforming_strings; = -- bytea @@ -917,12 +908,6 @@ SELECT '\x8000000000000000'::bytea::int8 AS "-9223372= 036854775808", -- -- test behavior of escape_string_warning and standard_conforming_strings= options -- -set escape_string_warning =3D off; -set standard_conforming_strings =3D off; - -show escape_string_warning; -show standard_conforming_strings; - set escape_string_warning =3D on; set standard_conforming_strings =3D on; = @@ -931,19 +916,11 @@ 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 =3D off; - -select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' a= s f4, 'ab\\\'cd' as f5, '\\\\' as f6; - set escape_string_warning =3D off; set standard_conforming_strings =3D 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 =3D off; - -select 'a\\bcd' as f1, 'a\\b\'cd' as f2, 'a\\b\'''cd' as f3, 'abcd\\' a= s f4, 'ab\\\'cd' as f5, '\\\\' as f6; - reset standard_conforming_strings; = = diff --git a/src/tutorial/syscat.source b/src/tutorial/syscat.source index 21ee574fd9e..15355bed7a9 100644 --- a/src/tutorial/syscat.source +++ b/src/tutorial/syscat.source @@ -17,10 +17,6 @@ -- SET search_path TO pg_catalog; = --- The LIKE pattern language requires underscores to be escaped, so make --- sure the backslashes are not misinterpreted. -SET standard_conforming_strings TO on; - -- -- lists the names of all database owners and the name of their database(= s) -- @@ -169,7 +165,6 @@ SELECT am.amname, n.nspname, opf.opfname, opr.oprname ORDER BY nspname, amname, opfname, oprname; = -- --- Reset the search path and standard_conforming_strings to their default= s +-- Reset the search path to default -- RESET search_path; -RESET standard_conforming_strings; -- = 2.43.7 ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name*0="v1-0002-Remove-server-side-support-for-standard_conformin.p"; name*1="atch"; charset="us-ascii" Content-ID: <3730908.1767135005.3@sss.pgh.pa.us> Content-Description: v1-0002-Remove-server-side-support-for-standard_conformin.patch Content-Transfer-Encoding: quoted-printable =46rom 562f29aedb0207420a8e3aeb807a9a1b18095fda Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 30 Dec 2025 15:42:22 -0500 Subject: [PATCH v1 2/4] Remove server-side support for !standard_conforming_strings. Mostly this consists of dropping scan.l's support for escape_string_warning, which is no longer reachable. (To see that, note that the warning subroutines are only called within the exclusive state, and after the change in the {xqstart} rule, state cannot be reached with yyextra->warn_on_first_escape true. So the subroutines can never warn.) This leaves the escape_string_warning GUC nonfunctional, but cleaning up that situation will come later. Also adjust assorted comments to reflect the fact that standard_conforming_strings =3D false is no longer possible locally, but we still have to allow for the possibility that a remote server might have it. Author: Tom Lane Discussion: https://postgr.es/m/3279216.1767072538@sss.pgh.pa.us --- .../pg_stat_statements/pg_stat_statements.c | 3 - contrib/test_decoding/test_decoding.c | 4 +- src/backend/parser/scan.l | 76 ++----------------- src/backend/utils/adt/quote.c | 8 +- src/backend/utils/adt/ruleutils.c | 6 +- src/backend/utils/misc/guc_tables.c | 5 +- src/include/parser/parser.h | 4 +- src/include/parser/scanner.h | 5 +- 8 files changed, 17 insertions(+), 94 deletions(-) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_= stat_statements/pg_stat_statements.c index 39208f80b5b..58892d12246 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -2991,9 +2991,6 @@ fill_in_constant_lengths(JumbleState *jstate, const = char *query, &ScanKeywords, ScanKeywordTokens); = - /* we don't want to re-emit any escape string warnings */ - yyextra.escape_string_warning =3D false; - /* Search for each constant, in sequence */ for (int i =3D 0; i < jstate->clocations_count; i++) { diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding= /test_decoding.c index 47094f86f5f..4c92f0eeffa 100644 --- a/contrib/test_decoding/test_decoding.c +++ b/contrib/test_decoding/test_decoding.c @@ -474,8 +474,8 @@ pg_decode_filter(LogicalDecodingContext *ctx, * Print literal `outputstr' already represented as string of type `typid= ' * into stringbuf `s'. * - * Some builtin types aren't quoted, the rest is quoted. Escaping is done= as - * if standard_conforming_strings were enabled. + * Some builtin types aren't quoted, the rest is quoted. Escaping is done + * per standard SQL rules. */ static void print_literal(StringInfo s, Oid typid, char *outputstr) diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index a67815339b7..cc88eea3708 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -60,14 +60,13 @@ fprintf_to_ereport(const char *fmt, const char *msg) } = /* - * GUC variables. This is a DIRECT violation of the warning given at the + * GUC variable. This is a DIRECT violation of the warning given at the * head of gram.y, ie flex/bison code must not depend on any GUC variable= s; - * as such, changing their values can induce very unintuitive behavior. - * But we shall have to live with it until we can remove these variables. + * as such, changing its value can induce very unintuitive behavior. + * In practice, backslash_quote is not too awful since it only controls + * whether to throw an error: it cannot change non-error results. */ int backslash_quote =3D BACKSLASH_QUOTE_SAFE_ENCODING; -bool escape_string_warning =3D true; -bool standard_conforming_strings =3D true; = /* * Constant data exported from this file. This array maps from the @@ -127,9 +126,6 @@ static void addunicode(char32_t c, yyscan_t yyscanner)= ; = #define lexer_errposition() scanner_errposition(*(yylloc), yyscanner) = -static void check_string_escape_warning(unsigned char ychar, core_yyscan_= t yyscanner); -static void check_escape_warning(core_yyscan_t yyscanner); - %} = %option reentrant @@ -543,17 +539,12 @@ other . } = {xqstart} { - yyextra->warn_on_first_escape =3D true; yyextra->saw_non_ascii =3D false; SET_YYLLOC(); - if (yyextra->standard_conforming_strings) - BEGIN(xq); - else - BEGIN(xe); + BEGIN(xq); startlit(); } {xestart} { - yyextra->warn_on_first_escape =3D false; yyextra->saw_non_ascii =3D false; SET_YYLLOC(); BEGIN(xe); @@ -561,12 +552,6 @@ other . } {xusstart} { SET_YYLLOC(); - if (!yyextra->standard_conforming_strings) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("unsafe use of string constant with Unicode escapes"), - errdetail("String constants with Unicode escapes cannot be used = when \"standard_conforming_strings\" is off."), - lexer_errposition())); BEGIN(xus); startlit(); } @@ -642,13 +627,6 @@ other . {xeunicode} { char32_t c =3D strtoul(yytext + 2, NULL, 16); = - /* - * For consistency with other productions, issue any - * escape warning with cursor pointing to start of string. - * We might want to change that, someday. - */ - check_escape_warning(yyscanner); - /* Remember start of overall string token ... */ PUSH_YYLLOC(); /* ... and set the error cursor to point at this esc seq */ @@ -715,14 +693,12 @@ other . errhint("Use '' to write quotes in strings. \\' is insecure in = client-only encodings."), lexer_errposition())); } - check_string_escape_warning(yytext[1], yyscanner); addlitchar(unescape_single_char(yytext[1], yyscanner), yyscanner); } {xeoctesc} { unsigned char c =3D strtoul(yytext + 1, NULL, 8); = - check_escape_warning(yyscanner); addlitchar(c, yyscanner); if (c =3D=3D '\0' || IS_HIGHBIT_SET(c)) yyextra->saw_non_ascii =3D true; @@ -730,7 +706,6 @@ other . {xehexesc} { unsigned char c =3D strtoul(yytext + 2, NULL, 16); = - check_escape_warning(yyscanner); addlitchar(c, yyscanner); if (c =3D=3D '\0' || IS_HIGHBIT_SET(c)) yyextra->saw_non_ascii =3D true; @@ -1263,8 +1238,6 @@ scanner_init(const char *str, yyext->keyword_tokens =3D keyword_tokens; = yyext->backslash_quote =3D backslash_quote; - yyext->escape_string_warning =3D escape_string_warning; - yyext->standard_conforming_strings =3D standard_conforming_strings; = /* * Make a scan buffer with special termination needed by flex. @@ -1420,45 +1393,6 @@ unescape_single_char(unsigned char c, core_yyscan_t= yyscanner) } } = -static void -check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner) -{ - if (ychar =3D=3D '\'') - { - if (yyextra->warn_on_first_escape && yyextra->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 strin= g syntax (E'...')."), - lexer_errposition())); - yyextra->warn_on_first_escape =3D false; /* warn only once per string *= / - } - else if (ychar =3D=3D '\\') - { - if (yyextra->warn_on_first_escape && yyextra->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'\\\\= '."), - lexer_errposition())); - yyextra->warn_on_first_escape =3D false; /* warn only once per string *= / - } - else - check_escape_warning(yyscanner); -} - -static void -check_escape_warning(core_yyscan_t yyscanner) -{ - if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) - ereport(WARNING, - (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), - errmsg("nonstandard use of escape in a string literal"), - errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."= ), - lexer_errposition())); - yyextra->warn_on_first_escape =3D false; /* warn only once per string */ -} - /* * Interface functions to make flex use palloc() instead of malloc(). * It'd be better to make these static, but flex insists otherwise. diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c index 551de59a07f..e62bf04a9f9 100644 --- a/src/backend/utils/adt/quote.c +++ b/src/backend/utils/adt/quote.c @@ -37,11 +37,9 @@ quote_ident(PG_FUNCTION_ARGS) * quote_literal_internal - * helper function for quote_literal and quote_literal_cstr * - * NOTE: think not to make this function's behavior change with - * standard_conforming_strings. We don't know where the result - * literal will be used, and so we must generate a result that - * will work with either setting. Take a look at what dblink - * uses this for before thinking you know better. + * NOTE: This must produce output that will work in old servers with + * standard_conforming_strings =3D off. It's used for example by + * dblink, which may send the result to another server. */ static size_t quote_literal_internal(char *dst, const char *src, size_t len) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/rul= eutils.c index 9f85eb86da1..61028db020f 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -11828,16 +11828,14 @@ simple_quote_literal(StringInfo buf, const char = *val) const char *valptr; = /* - * We form the string literal according to the prevailing setting of - * standard_conforming_strings; we never use E''. User is responsible fo= r - * making sure result is used correctly. + * We always form the string literal according to standard SQL rules. */ appendStringInfoChar(buf, '\''); for (valptr =3D val; *valptr; valptr++) { char ch =3D *valptr; = - if (SQL_STR_DOUBLE(ch, !standard_conforming_strings)) + if (SQL_STR_DOUBLE(ch, false)) appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch); } diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/= guc_tables.c index 04ab0a26608..beea9b00657 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -529,10 +529,11 @@ bool row_security; bool check_function_bodies =3D true; = /* - * This GUC exists solely for backward compatibility, check its definitio= n for - * details. + * These GUCs exist solely for backward compatibility. */ static bool default_with_oids =3D false; +static bool standard_conforming_strings =3D true; +static bool escape_string_warning =3D true; = bool current_role_is_superuser; = diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h index 350196cd641..cbf9a704dfb 100644 --- a/src/include/parser/parser.h +++ b/src/include/parser/parser.h @@ -52,10 +52,8 @@ typedef enum BACKSLASH_QUOTE_SAFE_ENCODING, } BackslashQuoteType; = -/* GUC variables in scan.l (every one of these is a bad idea :-() */ +/* GUC variable in scan.l */ extern PGDLLIMPORT int backslash_quote; -extern PGDLLIMPORT bool escape_string_warning; -extern PGDLLIMPORT bool standard_conforming_strings; = = /* Primary entry point for the raw parsing functions */ diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h index 8d202d5b284..f5806feb91d 100644 --- a/src/include/parser/scanner.h +++ b/src/include/parser/scanner.h @@ -85,8 +85,6 @@ typedef struct core_yy_extra_type * prevailing GUC settings. */ int backslash_quote; - bool escape_string_warning; - bool standard_conforming_strings; = /* * literalbuf is used to accumulate literal values when multiple rules a= re @@ -110,8 +108,7 @@ typedef struct core_yy_extra_type /* first part of UTF16 surrogate pair for Unicode escapes */ int32 utf16_first_part; = - /* state variables for literal-lexing warnings */ - bool warn_on_first_escape; + /* true if we need to verify valid encoding of current literal string */ bool saw_non_ascii; } core_yy_extra_type; = -- = 2.43.7 ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name*0="v1-0003-Adjust-pg_dump-and-pg_dumpall-for-standard_confor.p"; name*1="atch"; charset="us-ascii" Content-ID: <3730908.1767135005.4@sss.pgh.pa.us> Content-Description: v1-0003-Adjust-pg_dump-and-pg_dumpall-for-standard_confor.patch Content-Transfer-Encoding: quoted-printable =46rom 7ef994fff05dd375dbcb6e4724f569273a47c1b8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 30 Dec 2025 16:30:10 -0500 Subject: [PATCH v1 3/4] Adjust pg_dump and pg_dumpall for standard_conforming_strings change. The change needed here is to force standard_conforming_strings =3D on in the source server, so that any string literals it emits (while dumping views, expressions, etc) will be correctly formatted for a destination server that doesn't support the other setting. We long ago dropped support for source servers too old to accept that. Both programs will always emit "SET standard_conforming_strings =3D on" to ensure that the destination server is on board. While that's a no-op for v19 and later destinations, there's no reason to break compatibility with older destinations. This patch does not change the behavior of pg_restore, which will continue to use and emit the standard_conforming_strings setting it finds in the archive file. An archive with that turned off will not be safely restorable to >=3D v19 servers, but there's little pg_restore can do about that. We might as well preserve its functionality of being able to extract data usable by older destination servers. (Eventually that functionality will no longer be of interest to anyone, but I think that day is some ways off.) Since we're preserving pg_restore's behavior, none of the internal logic around AH->std_strings changes, and this patch is much smaller than you might expect. Author: Tom Lane Discussion: https://postgr.es/m/3279216.1767072538@sss.pgh.pa.us --- src/bin/pg_dump/pg_dump.c | 23 +++++++++++++++++------ src/bin/pg_dump/pg_dumpall.c | 20 ++++++++++---------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 27f6be3f0f8..053053b8d09 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -1428,7 +1428,6 @@ setup_connection(Archive *AH, const char *dumpencodi= ng, { DumpOptions *dopt =3D AH->dopt; PGconn *conn =3D GetConnection(AH); - const char *std_strings; = PQclear(ExecuteSqlQueryForSingleRow(AH, ALWAYS_SECURE_SEARCH_PATH_SQL)); = @@ -1443,15 +1442,27 @@ setup_connection(Archive *AH, const char *dumpenco= ding, } = /* - * Get the active encoding and the standard_conforming_strings setting, = so - * we know how to escape strings. + * Force standard_conforming_strings on, just in case we are dumping fro= m + * an old server that has it disabled. Without this, literals in views, + * expressions, etc, would be incorrect for modern servers. + */ + ExecuteSqlStatement(AH, "SET standard_conforming_strings =3D on"); + + /* + * And reflect that to AH->std_strings. You might think that we should + * just delete that variable and the code that checks it, but that would + * be problematic for pg_restore, which at least for now should still co= pe + * with archives containing the other setting (cf. processStdStringsEntr= y + * in pg_backup_archiver.c). + */ + AH->std_strings =3D true; + + /* + * Get the active encoding, so we know how to escape strings. */ AH->encoding =3D PQclientEncoding(conn); setFmtEncoding(AH->encoding); = - std_strings =3D PQparameterStatus(conn, "standard_conforming_strings"); - AH->std_strings =3D (std_strings && strcmp(std_strings, "on") =3D=3D 0); - /* * Set the role if requested. In a parallel dump worker, we'll be passe= d * use_role =3D=3D NULL, but AH->use_role is already set (if user specif= ied it diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 8fa04930399..ab435c4f4f5 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -204,7 +204,6 @@ main(int argc, char *argv[]) bool tablespaces_only =3D false; PGconn *conn; int encoding; - const char *std_strings; int c, ret; int optindex; @@ -568,14 +567,17 @@ main(int argc, char *argv[]) } = /* - * Get the active encoding and the standard_conforming_strings setting, = so - * we know how to escape strings. + * Force standard_conforming_strings on, just in case we are dumping fro= m + * an old server that has it disabled. Without this, literals in views, + * expressions, etc, would be incorrect for modern servers. + */ + executeCommand(conn, "SET standard_conforming_strings =3D on"); + + /* + * Get the active encoding, so we know how to escape strings. */ encoding =3D PQclientEncoding(conn); setFmtEncoding(encoding); - std_strings =3D PQparameterStatus(conn, "standard_conforming_strings"); - if (!std_strings) - std_strings =3D "off"; = /* Set the role if requested */ if (use_role) @@ -615,12 +617,10 @@ main(int argc, char *argv[]) /* Restore will need to write to the target cluster */ fprintf(OPF, "SET default_transaction_read_only =3D off;\n\n"); = - /* Replicate encoding and std_strings in output */ + /* Replicate encoding and standard_conforming_strings in output */ fprintf(OPF, "SET client_encoding =3D '%s';\n", pg_encoding_to_char(encoding)); - fprintf(OPF, "SET standard_conforming_strings =3D %s;\n", std_strings); - if (strcmp(std_strings, "off") =3D=3D 0) - fprintf(OPF, "SET escape_string_warning =3D off;\n"); + fprintf(OPF, "SET standard_conforming_strings =3D on;\n"); fprintf(OPF, "\n"); = if (!data_only && !statistics_only && !no_schema) -- = 2.43.7 ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="v1-0004-Remove-escape_string_warning.patch"; charset="us-ascii" Content-ID: <3730908.1767135005.5@sss.pgh.pa.us> Content-Description: v1-0004-Remove-escape_string_warning.patch Content-Transfer-Encoding: quoted-printable =46rom e1f791f96196c06afdb478e158a9c6322b83c45d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 30 Dec 2025 17:17:14 -0500 Subject: [PATCH v1 4/4] Remove escape_string_warning. Previous patches removed all the functionality of this GUC. We could keep it around as a vestigial setting, but I don't see the point of that. It's not like standard_conforming_strings, which many applications set and/or test for. Furthermore, any application that is touching it probably needs work anyway in the wake of disallowing standard_conforming_strings =3D off. Author: Tom Lane Discussion: https://postgr.es/m/3279216.1767072538@sss.pgh.pa.us --- contrib/hstore/expected/hstore.out | 1 - contrib/hstore/sql/hstore.sql | 2 -- doc/src/sgml/config.sgml | 15 --------- src/backend/utils/misc/guc_parameters.dat | 6 ---- src/backend/utils/misc/guc_tables.c | 1 - src/backend/utils/misc/postgresql.conf.sample | 1 - src/bin/pg_dump/pg_backup_archiver.c | 2 -- src/fe_utils/string_utils.c | 4 +-- src/test/regress/expected/strings.out | 32 ------------------- src/test/regress/sql/strings.sql | 19 ----------- 10 files changed, 2 insertions(+), 81 deletions(-) diff --git a/contrib/hstore/expected/hstore.out b/contrib/hstore/expected/= hstore.out index 1836c9acf39..acea8806ba4 100644 --- a/contrib/hstore/expected/hstore.out +++ b/contrib/hstore/expected/hstore.out @@ -7,7 +7,6 @@ WHERE opc.oid >=3D 16384 AND NOT amvalidate(opc.oid); --------+--------- (0 rows) = -set escape_string_warning=3Doff; --hstore; select ''::hstore; hstore = diff --git a/contrib/hstore/sql/hstore.sql b/contrib/hstore/sql/hstore.sql index efef91292a3..8ae95e8a510 100644 --- a/contrib/hstore/sql/hstore.sql +++ b/contrib/hstore/sql/hstore.sql @@ -5,8 +5,6 @@ SELECT amname, opcname FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid =3D opcmethod WHERE opc.oid >=3D 16384 AND NOT amvalidate(opc.oid); = -set escape_string_warning=3Doff; - --hstore; = select ''::hstore; diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 9ca6b73aa8b..8b31a28c32b 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -11416,21 +11416,6 @@ dynamic_library_path =3D '/usr/local/lib/postgres= ql:$libdir' = - - escape_string_warning (boolean) - stringsescape warning - - escape_string_warning configuration pa= rameter - - - - - This parameter no longer does anything, because - standard_conforming_strings cannot be turned o= ff. - - - - lo_compat_privileges (boolean= ) diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils= /misc/guc_parameters.dat index 7f23186506a..2560449355a 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -991,12 +991,6 @@ boot_val =3D> 'true', }, = -{ name =3D> 'escape_string_warning', type =3D> 'bool', context =3D> 'PGC_= USERSET', group =3D> 'COMPAT_OPTIONS_PREVIOUS', - short_desc =3D> 'Warn about backslash escapes in ordinary string litera= ls.', - variable =3D> 'escape_string_warning', - boot_val =3D> 'true', -}, - { name =3D> 'event_source', type =3D> 'string', context =3D> 'PGC_POSTMAS= TER', group =3D> 'LOGGING_WHERE', short_desc =3D> 'Sets the application name used to identify PostgreSQL = messages in the event log.', variable =3D> 'event_source', diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/= guc_tables.c index beea9b00657..b560ad83940 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -533,7 +533,6 @@ bool check_function_bodies =3D true; */ static bool default_with_oids =3D false; static bool standard_conforming_strings =3D true; -static bool escape_string_warning =3D true; = bool current_role_is_superuser; = diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/u= tils/misc/postgresql.conf.sample index ec356f62ad1..c4f92fcdac8 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -847,7 +847,6 @@ = #array_nulls =3D on #backslash_quote =3D safe_encoding # on, off, or safe_encoding -#escape_string_warning =3D on #lo_compat_privileges =3D off #quote_all_identifiers =3D off #synchronize_seqscans =3D on diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_bac= kup_archiver.c index 4a63f7392ae..18d3822fd82 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -3426,8 +3426,6 @@ _doSetFixedOutputState(ArchiveHandle *AH) = /* Avoid annoying notices etc */ ahprintf(AH, "SET client_min_messages =3D warning;\n"); - if (!AH->public.std_strings) - ahprintf(AH, "SET escape_string_warning =3D off;\n"); = /* Adjust row-security state */ if (ropt && ropt->enable_row_security) diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c index 130d1020d50..31fe50880f3 100644 --- a/src/fe_utils/string_utils.c +++ b/src/fe_utils/string_utils.c @@ -449,9 +449,9 @@ appendStringLiteralConn(PQExpBuffer buf, const char *s= tr, PGconn *conn) = /* * XXX This is a kluge to silence escape_string_warning in our utility - * programs. It should go away someday. + * programs. It can go away once pre-v19 servers are out of support. */ - if (strchr(str, '\\') !=3D NULL && PQserverVersion(conn) >=3D 80100) + if (strchr(str, '\\') !=3D NULL && PQserverVersion(conn) < 190000) { /* ensure we are not adjacent to an identifier */ if (buf->len > 0 && buf->data[buf->len - 1] !=3D ' ') diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expe= cted/strings.out index 6eb92bc8442..5f2b5c39173 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -2837,38 +2837,6 @@ SELECT '\x8000000000000000'::bytea::int8 AS "-92233= 72036854775808", -9223372036854775808 | 9223372036854775807 (1 row) = --- --- test behavior of escape_string_warning and standard_conforming_strings= options --- -set escape_string_warning =3D on; -set standard_conforming_strings =3D 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; - f1 | f2 | f3 | f4 | f5 | f6 = --------+--------+---------+-------+--------+---- - a\bcd | a\b'cd | a\b''cd | abcd\ | ab\'cd | \\ -(1 row) - -set escape_string_warning =3D off; -set standard_conforming_strings =3D 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) - -reset standard_conforming_strings; -- -- Additional string functions -- diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strin= gs.sql index 531d409542f..37c0893ae83 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -905,25 +905,6 @@ SELECT '\x80000000'::bytea::int4 AS "-2147483648", '\= x7FFFFFFF'::bytea::int4 AS SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808", '\x7FFFFFFFFFFFFFFF'::bytea::int8 AS "9223372036854775807"; = --- --- test behavior of escape_string_warning and standard_conforming_strings= options --- -set escape_string_warning =3D on; -set standard_conforming_strings =3D 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 escape_string_warning =3D off; -set standard_conforming_strings =3D 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; - -reset standard_conforming_strings; - - -- -- Additional string functions -- -- = 2.43.7 ------- =_aaaaaaaaaa0--