mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-05 19:09:58 +08:00
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.)
This commit is contained in:
parent
f5f2c2de16
commit
eb213acfe2
@ -2816,6 +2816,9 @@ fill_in_constant_lengths(pgssJumbleState *jstate, const char *query)
|
||||
ScanKeywords,
|
||||
NumScanKeywords);
|
||||
|
||||
/* we don't want to re-emit any escape string warnings */
|
||||
yyextra.escape_string_warning = false;
|
||||
|
||||
/* Search for each constant, in sequence */
|
||||
for (i = 0; i < jstate->clocations_count; i++)
|
||||
{
|
||||
|
@ -505,7 +505,7 @@ other .
|
||||
yyextra->warn_on_first_escape = true;
|
||||
yyextra->saw_non_ascii = false;
|
||||
SET_YYLLOC();
|
||||
if (standard_conforming_strings)
|
||||
if (yyextra->standard_conforming_strings)
|
||||
BEGIN(xq);
|
||||
else
|
||||
BEGIN(xe);
|
||||
@ -520,7 +520,7 @@ other .
|
||||
}
|
||||
{xusstart} {
|
||||
SET_YYLLOC();
|
||||
if (!standard_conforming_strings)
|
||||
if (!yyextra->standard_conforming_strings)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("unsafe use of string constant with Unicode escapes"),
|
||||
@ -622,8 +622,8 @@ other .
|
||||
<xe>{xeescape} {
|
||||
if (yytext[1] == '\'')
|
||||
{
|
||||
if (backslash_quote == BACKSLASH_QUOTE_OFF ||
|
||||
(backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
|
||||
if (yyextra->backslash_quote == BACKSLASH_QUOTE_OFF ||
|
||||
(yyextra->backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
|
||||
PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding())))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
|
||||
@ -1074,6 +1074,10 @@ scanner_init(const char *str,
|
||||
yyext->keywords = keywords;
|
||||
yyext->num_keywords = num_keywords;
|
||||
|
||||
yyext->backslash_quote = backslash_quote;
|
||||
yyext->escape_string_warning = escape_string_warning;
|
||||
yyext->standard_conforming_strings = standard_conforming_strings;
|
||||
|
||||
/*
|
||||
* Make a scan buffer with special termination needed by flex.
|
||||
*/
|
||||
@ -1433,7 +1437,7 @@ check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner)
|
||||
{
|
||||
if (ychar == '\'')
|
||||
{
|
||||
if (yyextra->warn_on_first_escape && escape_string_warning)
|
||||
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"),
|
||||
@ -1443,7 +1447,7 @@ check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner)
|
||||
}
|
||||
else if (ychar == '\\')
|
||||
{
|
||||
if (yyextra->warn_on_first_escape && escape_string_warning)
|
||||
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"),
|
||||
@ -1458,7 +1462,7 @@ check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner)
|
||||
static void
|
||||
check_escape_warning(core_yyscan_t yyscanner)
|
||||
{
|
||||
if (yyextra->warn_on_first_escape && escape_string_warning)
|
||||
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"),
|
||||
|
@ -77,6 +77,16 @@ typedef struct core_yy_extra_type
|
||||
const ScanKeyword *keywords;
|
||||
int num_keywords;
|
||||
|
||||
/*
|
||||
* Scanner settings to use. These are initialized from the corresponding
|
||||
* GUC variables by scanner_init(). Callers can modify them after
|
||||
* scanner_init() if they don't want the scanner's behavior to follow the
|
||||
* prevailing GUC settings.
|
||||
*/
|
||||
int backslash_quote;
|
||||
bool escape_string_warning;
|
||||
bool standard_conforming_strings;
|
||||
|
||||
/*
|
||||
* literalbuf is used to accumulate literal values when multiple rules are
|
||||
* needed to parse a single literal. Call startlit() to reset buffer to
|
||||
|
Loading…
Reference in New Issue
Block a user