Skip to content

Commit eb213ac

Browse files
committed
Prevent duplicate escape-string warnings when using pg_stat_statements.
contrib/pg_stat_statements will sometimes run the core lexer a second time on submitted statements. Formerly, if you had standard_conforming_strings turned off, this led to sometimes getting two copies of any warnings enabled by escape_string_warning. While this is probably no longer a big deal in the field, it's a pain for regression testing. To fix, change the lexer so it doesn't consult the escape_string_warning GUC variable directly, but looks at a copy in the core_yy_extra_type state struct. Then, pg_stat_statements can change that copy to disable warnings while it's redoing the lexing. It seemed like a good idea to make this happen for all three of the GUCs consulted by the lexer, not just escape_string_warning. There's not an immediate use-case for callers to adjust the other two AFAIK, but making it possible is easy enough and seems like good future-proofing. Arguably this is a bug fix, but there doesn't seem to be enough interest to justify a back-patch. We'd not be able to back-patch exactly as-is anyway, for fear of breaking ABI compatibility of the struct. (We could perhaps back-patch the addition of only escape_string_warning by adding it at the end of the struct, where there's currently alignment padding space.)
1 parent f5f2c2d commit eb213ac

File tree

3 files changed

+24
-7
lines changed

3 files changed

+24
-7
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,6 +2816,9 @@ fill_in_constant_lengths(pgssJumbleState *jstate, const char *query)
28162816
ScanKeywords,
28172817
NumScanKeywords);
28182818

2819+
/* we don't want to re-emit any escape string warnings */
2820+
yyextra.escape_string_warning = false;
2821+
28192822
/* Search for each constant, in sequence */
28202823
for (i = 0; i < jstate->clocations_count; i++)
28212824
{

src/backend/parser/scan.l

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ other .
505505
yyextra->warn_on_first_escape = true;
506506
yyextra->saw_non_ascii = false;
507507
SET_YYLLOC();
508-
if (standard_conforming_strings)
508+
if (yyextra->standard_conforming_strings)
509509
BEGIN(xq);
510510
else
511511
BEGIN(xe);
@@ -520,7 +520,7 @@ other .
520520
}
521521
{xusstart} {
522522
SET_YYLLOC();
523-
if (!standard_conforming_strings)
523+
if (!yyextra->standard_conforming_strings)
524524
ereport(ERROR,
525525
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
526526
errmsg("unsafe use of string constant with Unicode escapes"),
@@ -622,8 +622,8 @@ other .
622622
<xe>{xeescape} {
623623
if (yytext[1] == '\'')
624624
{
625-
if (backslash_quote == BACKSLASH_QUOTE_OFF ||
626-
(backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
625+
if (yyextra->backslash_quote == BACKSLASH_QUOTE_OFF ||
626+
(yyextra->backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
627627
PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding())))
628628
ereport(ERROR,
629629
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
@@ -1074,6 +1074,10 @@ scanner_init(const char *str,
10741074
yyext->keywords = keywords;
10751075
yyext->num_keywords = num_keywords;
10761076

1077+
yyext->backslash_quote = backslash_quote;
1078+
yyext->escape_string_warning = escape_string_warning;
1079+
yyext->standard_conforming_strings = standard_conforming_strings;
1080+
10771081
/*
10781082
* Make a scan buffer with special termination needed by flex.
10791083
*/
@@ -1433,7 +1437,7 @@ check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner)
14331437
{
14341438
if (ychar == '\'')
14351439
{
1436-
if (yyextra->warn_on_first_escape && escape_string_warning)
1440+
if (yyextra->warn_on_first_escape && yyextra->escape_string_warning)
14371441
ereport(WARNING,
14381442
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
14391443
errmsg("nonstandard use of \\' in a string literal"),
@@ -1443,7 +1447,7 @@ check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner)
14431447
}
14441448
else if (ychar == '\\')
14451449
{
1446-
if (yyextra->warn_on_first_escape && escape_string_warning)
1450+
if (yyextra->warn_on_first_escape && yyextra->escape_string_warning)
14471451
ereport(WARNING,
14481452
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
14491453
errmsg("nonstandard use of \\\\ in a string literal"),
@@ -1458,7 +1462,7 @@ check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner)
14581462
static void
14591463
check_escape_warning(core_yyscan_t yyscanner)
14601464
{
1461-
if (yyextra->warn_on_first_escape && escape_string_warning)
1465+
if (yyextra->warn_on_first_escape && yyextra->escape_string_warning)
14621466
ereport(WARNING,
14631467
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
14641468
errmsg("nonstandard use of escape in a string literal"),

src/include/parser/scanner.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ typedef struct core_yy_extra_type
7777
const ScanKeyword *keywords;
7878
int num_keywords;
7979

80+
/*
81+
* Scanner settings to use. These are initialized from the corresponding
82+
* GUC variables by scanner_init(). Callers can modify them after
83+
* scanner_init() if they don't want the scanner's behavior to follow the
84+
* prevailing GUC settings.
85+
*/
86+
int backslash_quote;
87+
bool escape_string_warning;
88+
bool standard_conforming_strings;
89+
8090
/*
8191
* literalbuf is used to accumulate literal values when multiple rules are
8292
* needed to parse a single literal. Call startlit() to reset buffer to

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy