mirror of
https://github.com/postgres/postgres.git
synced 2025-07-24 14:22:24 +03:00
Return yyparse() result not via global variable
Instead of passing the parse result from yyparse() via a global variable, pass it via a function output argument. This complements earlier work to make the parsers reentrant. Discussion: Discussion: https://www.postgresql.org/message-id/flat/eb6faeac-2a8a-4b69-9189-c33c520e5b7b@eisentraut.org
This commit is contained in:
@ -25,10 +25,6 @@
|
||||
#include "repl_gram.h"
|
||||
|
||||
|
||||
/* Result of the parsing is returned here */
|
||||
Node *replication_parse_result;
|
||||
|
||||
|
||||
/*
|
||||
* Bison doesn't allocate anything that needs to live across parser calls,
|
||||
* so we can easily have it use palloc instead of malloc. This prevents
|
||||
@ -39,6 +35,7 @@ Node *replication_parse_result;
|
||||
|
||||
%}
|
||||
|
||||
%parse-param {Node **replication_parse_result_p}
|
||||
%parse-param {yyscan_t yyscanner}
|
||||
%lex-param {yyscan_t yyscanner}
|
||||
%pure-parser
|
||||
@ -104,7 +101,7 @@ Node *replication_parse_result;
|
||||
|
||||
firstcmd: command opt_semicolon
|
||||
{
|
||||
replication_parse_result = $1;
|
||||
*replication_parse_result_p = $1;
|
||||
|
||||
(void) yynerrs; /* suppress compiler warning */
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
|
||||
uint32 hi,
|
||||
lo;
|
||||
if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
|
||||
replication_yyerror(yyscanner, "invalid streaming start location");
|
||||
replication_yyerror(NULL, yyscanner, "invalid streaming start location");
|
||||
yylval->recptr = ((uint64) hi) << 32 | lo;
|
||||
return RECPTR;
|
||||
}
|
||||
@ -213,7 +213,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
<xq,xd><<EOF>> { replication_yyerror(yyscanner, "unterminated quoted string"); }
|
||||
<xq,xd><<EOF>> { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); }
|
||||
|
||||
|
||||
<<EOF>> {
|
||||
@ -252,8 +252,12 @@ addlitchar(unsigned char ychar, yyscan_t yyscanner)
|
||||
appendStringInfoChar(&yyextra->litbuf, ychar);
|
||||
}
|
||||
|
||||
/*
|
||||
* (The first argument is enforced by Bison to match the first argument of
|
||||
* yyparse(), but it is not used here.)
|
||||
*/
|
||||
void
|
||||
replication_yyerror(yyscan_t yyscanner, const char *message)
|
||||
replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
|
@ -996,13 +996,13 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source)
|
||||
int parse_rc;
|
||||
SyncRepConfigData *pconf;
|
||||
|
||||
/* Reset communication variables to ensure a fresh start */
|
||||
syncrep_parse_result = NULL;
|
||||
syncrep_parse_error_msg = NULL;
|
||||
/* Result of parsing is returned in one of these two variables */
|
||||
SyncRepConfigData *syncrep_parse_result = NULL;
|
||||
char *syncrep_parse_error_msg = NULL;
|
||||
|
||||
/* Parse the synchronous_standby_names string */
|
||||
syncrep_scanner_init(*newval, &scanner);
|
||||
parse_rc = syncrep_yyparse(scanner);
|
||||
parse_rc = syncrep_yyparse(&syncrep_parse_result, &syncrep_parse_error_msg, scanner);
|
||||
syncrep_scanner_finish(scanner);
|
||||
|
||||
if (parse_rc != 0 || syncrep_parse_result == NULL)
|
||||
|
@ -19,10 +19,6 @@
|
||||
|
||||
#include "syncrep_gram.h"
|
||||
|
||||
/* Result of parsing is returned in one of these two variables */
|
||||
SyncRepConfigData *syncrep_parse_result;
|
||||
char *syncrep_parse_error_msg;
|
||||
|
||||
static SyncRepConfigData *create_syncrep_config(const char *num_sync,
|
||||
List *members, uint8 syncrep_method);
|
||||
|
||||
@ -36,7 +32,10 @@ static SyncRepConfigData *create_syncrep_config(const char *num_sync,
|
||||
|
||||
%}
|
||||
|
||||
%parse-param {SyncRepConfigData **syncrep_parse_result_p}
|
||||
%parse-param {char **syncrep_parse_error_msg_p}
|
||||
%parse-param {yyscan_t yyscanner}
|
||||
%lex-param {char **syncrep_parse_error_msg_p}
|
||||
%lex-param {yyscan_t yyscanner}
|
||||
%pure-parser
|
||||
%expect 0
|
||||
@ -60,7 +59,7 @@ static SyncRepConfigData *create_syncrep_config(const char *num_sync,
|
||||
%%
|
||||
result:
|
||||
standby_config {
|
||||
syncrep_parse_result = $1;
|
||||
*syncrep_parse_result_p = $1;
|
||||
(void) yynerrs; /* suppress compiler warning */
|
||||
}
|
||||
;
|
||||
|
@ -42,6 +42,13 @@ struct syncrep_yy_extra_type
|
||||
StringInfoData xdbuf;
|
||||
};
|
||||
|
||||
/*
|
||||
* Better keep this definition here than put it in replication/syncrep.h and
|
||||
* save a bit of duplication. Putting it in replication/syncrep.h would leak
|
||||
* the definition to other parts and possibly affect other scanners.
|
||||
*/
|
||||
#define YY_DECL extern int syncrep_yylex(union YYSTYPE *yylval_param, char **syncrep_parse_error_msg_p, yyscan_t yyscanner)
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
|
||||
%}
|
||||
@ -104,7 +111,7 @@ xdinside [^"]+
|
||||
return NAME;
|
||||
}
|
||||
<xd><<EOF>> {
|
||||
syncrep_yyerror(yyscanner, "unterminated quoted identifier");
|
||||
syncrep_yyerror(NULL, syncrep_parse_error_msg_p, yyscanner, "unterminated quoted identifier");
|
||||
return JUNK;
|
||||
}
|
||||
|
||||
@ -136,12 +143,21 @@ xdinside [^"]+
|
||||
#undef yyextra
|
||||
#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
|
||||
|
||||
/* Needs to be here for access to yytext */
|
||||
/*
|
||||
* This yyerror() function does not raise an error (elog or similar), it just
|
||||
* collects the error message in *syncrep_parse_error_msg_p and leaves it to
|
||||
* the ultimate caller of the syncrep parser to raise the error. (The
|
||||
* ultimate caller will do that with special GUC error functions.)
|
||||
*
|
||||
* (The first argument is enforced by Bison to match the first argument of
|
||||
* yyparse(), but it is not used here.)
|
||||
*/
|
||||
void
|
||||
syncrep_yyerror(yyscan_t yyscanner, const char *message)
|
||||
syncrep_yyerror(SyncRepConfigData **syncrep_parse_result_p, char **syncrep_parse_error_msg_p, yyscan_t yyscanner, const char *message)
|
||||
{
|
||||
struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext
|
||||
* macro */
|
||||
char *syncrep_parse_error_msg = *syncrep_parse_error_msg_p;
|
||||
|
||||
/* report only the first error in a parse operation */
|
||||
if (syncrep_parse_error_msg)
|
||||
|
@ -2017,7 +2017,7 @@ exec_replication_command(const char *cmd_string)
|
||||
/*
|
||||
* Looks like a WalSender command, so parse it.
|
||||
*/
|
||||
parse_rc = replication_yyparse(scanner);
|
||||
parse_rc = replication_yyparse(&cmd_node, scanner);
|
||||
if (parse_rc != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
@ -2025,8 +2025,6 @@ exec_replication_command(const char *cmd_string)
|
||||
parse_rc)));
|
||||
replication_scanner_finish(scanner);
|
||||
|
||||
cmd_node = replication_parse_result;
|
||||
|
||||
/*
|
||||
* Report query to various monitoring facilities. For this purpose, we
|
||||
* report replication commands just like SQL commands.
|
||||
|
Reference in New Issue
Block a user