!1521 修正SPI受自定义解析器影响而导致PL/pgSQL在启用自定义解析器时可能导致非逾期结果的问题

Merge pull request !1521 from bucoo/master
This commit is contained in:
opengauss-bot
2022-08-11 03:09:59 +00:00
committed by Gitee
4 changed files with 56 additions and 48 deletions

View File

@ -873,7 +873,8 @@ void LoadDolphinIfNeeded()
* we've seen a COMMIT or ABORT command; when we are in abort state, other
* commands are not processed any further than the raw parse stage.
*/
List* pg_parse_query(const char* query_string, List** query_string_locationlist)
List* pg_parse_query(const char* query_string, List** query_string_locationlist,
List* (*parser_hook)(const char*, List**))
{
List* raw_parsetree_list = NULL;
PGSTAT_INIT_TIME_RECORD();
@ -885,15 +886,17 @@ List* pg_parse_query(const char* query_string, List** query_string_locationlist)
PGSTAT_START_TIME_RECORD();
List* (*parser_hook)(const char*, List**) = raw_parser;
if (parser_hook == NULL) {
parser_hook = raw_parser;
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->attr.attr_sql.whale || u_sess->attr.attr_sql.dolphin) {
int id = GetCustomParserId();
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id];
if (u_sess->attr.attr_sql.whale || u_sess->attr.attr_sql.dolphin) {
int id = GetCustomParserId();
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id];
}
}
}
#endif
}
raw_parsetree_list = parser_hook(query_string, query_string_locationlist);
PGSTAT_END_TIME_RECORD(PARSE_TIME);

View File

@ -58,7 +58,7 @@ static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamL
void _SPI_prepare_plan(const char *src, SPIPlanPtr plan);
#ifdef PGXC
static void _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree, SPIPlanPtr plan);
static void _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree, SPIPlanPtr plan, parse_query_func parser);
#endif
void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
@ -734,7 +734,7 @@ void SPI_restore_connection(void)
* bypass the parse stage. This is achieved here by calling
* _SPI_pgxc_prepare_plan which accepts a parse tree.
*/
int SPI_execute_direct(const char *remote_sql, char *nodename)
int SPI_execute_direct(const char *remote_sql, char *nodename, parse_query_func parser)
{
_SPI_plan plan;
ExecDirectStmt *stmt = makeNode(ExecDirectStmt);
@ -761,7 +761,7 @@ int SPI_execute_direct(const char *remote_sql, char *nodename)
plan.spi_key = INVALID_SPI_KEY;
/* Now pass the ExecDirectStmt parsetree node */
_SPI_pgxc_prepare_plan(execdirect.data, list_make1(stmt), &plan);
_SPI_pgxc_prepare_plan(execdirect.data, list_make1(stmt), &plan, parser);
res = _SPI_execute_plan(&plan, NULL, InvalidSnapshot, InvalidSnapshot, false, true, 0, true);
@ -775,7 +775,7 @@ int SPI_execute_direct(const char *remote_sql, char *nodename)
* Parse, plan, and execute a query string
* @isCollectParam: default false, is used to collect sql info in sqladvisor online mode.
*/
int SPI_execute(const char *src, bool read_only, long tcount, bool isCollectParam)
int SPI_execute(const char *src, bool read_only, long tcount, bool isCollectParam, parse_query_func parser)
{
_SPI_plan plan;
@ -794,7 +794,7 @@ int SPI_execute(const char *src, bool read_only, long tcount, bool isCollectPara
plan.cursor_options = 0;
plan.spi_key = INVALID_SPI_KEY;
_SPI_prepare_oneshot_plan(src, &plan);
_SPI_prepare_oneshot_plan(src, &plan, parser);
res = _SPI_execute_plan(&plan, NULL, InvalidSnapshot, InvalidSnapshot, read_only, true, tcount);
@ -810,9 +810,9 @@ int SPI_execute(const char *src, bool read_only, long tcount, bool isCollectPara
}
/* Obsolete version of SPI_execute */
int SPI_exec(const char *src, long tcount)
int SPI_exec(const char *src, long tcount, parse_query_func parser)
{
return SPI_execute(src, false, tcount);
return SPI_execute(src, false, tcount, false, parser);
}
/* Execute a previously prepared plan */
@ -907,7 +907,7 @@ int SPI_execute_snapshot(SPIPlanPtr plan, Datum *Values, const char *Nulls, Snap
* SPI_execute_plan.
*/
int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only,
long tcount, Cursor_Data *cursor_data)
long tcount, Cursor_Data *cursor_data, parse_query_func parser)
{
_SPI_plan plan;
@ -935,7 +935,7 @@ int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Valu
ParamListInfo param_list_info = _SPI_convert_params(nargs, argtypes, Values, Nulls, cursor_data);
_SPI_prepare_oneshot_plan(src, &plan);
_SPI_prepare_oneshot_plan(src, &plan, parser);
res = _SPI_execute_plan(&plan, param_list_info, InvalidSnapshot, InvalidSnapshot, read_only, true, tcount);
#ifdef ENABLE_MULTIPLE_NODES
@ -948,12 +948,12 @@ int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Valu
return res;
}
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes, parse_query_func parser)
{
return SPI_prepare_cursor(src, nargs, argtypes, 0);
return SPI_prepare_cursor(src, nargs, argtypes, 0, parser);
}
SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions)
SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions, parse_query_func parser)
{
_SPI_plan plan;
@ -984,7 +984,7 @@ SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cur
u_sess->SPI_cxt._current->spi_hash_key = INVALID_SPI_KEY;
PG_TRY();
{
_SPI_prepare_plan(src, &plan);
_SPI_prepare_plan(src, &plan, parser);
}
PG_CATCH();
{
@ -1003,7 +1003,8 @@ SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cur
return result;
}
SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)
SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions,
parse_query_func parser)
{
_SPI_plan plan;
@ -1030,7 +1031,7 @@ SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void
plan.spi_key = INVALID_SPI_KEY;
plan.id = (uint32)-1;
_SPI_prepare_plan(src, &plan);
_SPI_prepare_plan(src, &plan, parser);
/* copy plan to procedure context */
SPIPlanPtr result = _SPI_make_plan_non_temp(&plan);
@ -1497,7 +1498,7 @@ Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const c
* Parse and plan a query and open it as a portal.
*/
Portal SPI_cursor_open_with_args(const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values,
const char *Nulls, bool read_only, int cursorOptions)
const char *Nulls, bool read_only, int cursorOptions, parse_query_func parser)
{
_SPI_plan plan;
errno_t errorno = EOK;
@ -1542,7 +1543,7 @@ Portal SPI_cursor_open_with_args(const char *name, const char *src, int nargs, O
u_sess->SPI_cxt._current->spi_hash_key = INVALID_SPI_KEY;
PG_TRY();
{
_SPI_prepare_plan(src, &plan);
_SPI_prepare_plan(src, &plan, parser);
}
PG_CATCH();
{
@ -2208,10 +2209,10 @@ void spi_printtup(TupleTableSlot *slot, DestReceiver *self)
* what we are creating is a "temporary" SPIPlan. Cruft generated during
* parsing is also left in CurrentMemoryContext.
*/
void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
void _SPI_prepare_plan(const char *src, SPIPlanPtr plan, parse_query_func parser)
{
#ifdef PGXC
_SPI_pgxc_prepare_plan(src, NULL, plan);
_SPI_pgxc_prepare_plan(src, NULL, plan, parser);
}
/*
@ -2220,7 +2221,7 @@ void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
* called for internally executed execute-direct statements that are
* transparent to the user.
*/
static void _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree, SPIPlanPtr plan)
static void _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree, SPIPlanPtr plan, parse_query_func parser)
{
#endif
List *raw_parsetree_list = NIL;
@ -2245,7 +2246,7 @@ static void _SPI_pgxc_prepare_plan(const char *src, List *src_parsetree, SPIPlan
raw_parsetree_list = src_parsetree;
else
#endif
raw_parsetree_list = pg_parse_query(src);
raw_parsetree_list = pg_parse_query(src, NULL, parser);
/*
* Do parse analysis and rule rewrite for each raw parsetree, storing the
* results into unsaved plancache entries.
@ -2398,7 +2399,7 @@ static void SPIParseOneShotPlan(CachedPlanSource* plansource, SPIPlanPtr plan)
* what we are creating is a "temporary" SPIPlan. Cruft generated during
* parsing is also left in CurrentMemoryContext.
*/
void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan, parse_query_func parser)
{
List *raw_parsetree_list = NIL;
List *plancache_list = NIL;
@ -2417,7 +2418,7 @@ void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
/*
* Parse the request string into a list of raw parse trees.
*/
raw_parsetree_list = pg_parse_query(src, &query_string_locationlist);
raw_parsetree_list = pg_parse_query(src, &query_string_locationlist, parser);
/*
* Construct plancache entries, but don't do parse analysis yet.
@ -3690,7 +3691,7 @@ DestReceiver *createAnalyzeSPIDestReceiver(CommandDest dest)
* Returns: void
*/
void spi_exec_with_callback(CommandDest dest, const char *src, bool read_only, long tcount, bool direct_call,
void (*callbackFn)(void *), void *clientData)
void (*callbackFn)(void *), void *clientData, parse_query_func parser)
{
bool connected = false;
int ret = 0;
@ -3707,7 +3708,7 @@ void spi_exec_with_callback(CommandDest dest, const char *src, bool read_only, l
elog(DEBUG1, "Executing SQL: %s", src);
/* Do the query. */
ret = SPI_execute(src, read_only, tcount);
ret = SPI_execute(src, read_only, tcount, false, parser);
Assert(ret > 0);
if (direct_call && callbackFn != NULL) {
@ -3770,9 +3771,9 @@ List* _SPI_get_querylist(SPIPlanPtr plan)
return plan ? plan->stmt_list : NULL;
}
void _SPI_prepare_oneshot_plan_for_validator(const char *src, SPIPlanPtr plan)
void _SPI_prepare_oneshot_plan_for_validator(const char *src, SPIPlanPtr plan, parse_query_func parser)
{
_SPI_prepare_oneshot_plan(src, plan);
_SPI_prepare_oneshot_plan(src, plan, parser);
}
void InitSPIPlanCxt()

View File

@ -66,6 +66,10 @@ typedef struct SPICachedPlanStack {
#define SPI_OK_MERGE 15
#define SPI_OPT_NONATOMIC (1 << 0)
typedef List* (*parse_query_func)(const char *query_string, List **query_string_locationlist);
/* in postgres.cpp, avoid include tcopprot.h */
extern List* raw_parser(const char* query_string, List** query_string_locationlist);
extern THR_LOCAL PGDLLIMPORT uint32 SPI_processed;
extern THR_LOCAL PGDLLIMPORT SPITupleTable* SPI_tuptable;
extern THR_LOCAL PGDLLIMPORT int SPI_result;
@ -79,19 +83,18 @@ extern void SPI_pop(void);
extern bool SPI_push_conditional(void);
extern void SPI_pop_conditional(bool pushed);
extern void SPI_restore_connection(void);
extern int SPI_execute(const char* src, bool read_only, long tcount, bool isCollectParam = false);
extern int SPI_execute(const char* src, bool read_only, long tcount, bool isCollectParam = false, parse_query_func parser = raw_parser);
extern int SPI_execute_plan(SPIPlanPtr plan, Datum* Values, const char* Nulls, bool read_only, long tcount);
extern int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount);
extern int SPI_exec(const char* src, long tcount);
extern int SPI_exec(const char* src, long tcount, parse_query_func parser = raw_parser);
extern int SPI_execp(SPIPlanPtr plan, Datum* Values, const char* Nulls, long tcount);
extern int SPI_execute_snapshot(SPIPlanPtr plan, Datum* Values, const char* Nulls, Snapshot snapshot,
Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount);
extern int SPI_execute_with_args(const char* src, int nargs, Oid* argtypes, Datum* Values, const char* Nulls,
bool read_only, long tcount, Cursor_Data* cursor_data);
extern SPIPlanPtr SPI_prepare(const char* src, int nargs, Oid* argtypes);
extern SPIPlanPtr SPI_prepare_cursor(const char* src, int nargs, Oid* argtypes, int cursorOptions);
extern SPIPlanPtr SPI_prepare_params(
const char* src, ParserSetupHook parserSetup, void* parserSetupArg, int cursorOptions);
bool read_only, long tcount, Cursor_Data* cursor_data, parse_query_func parser = raw_parser);
extern SPIPlanPtr SPI_prepare(const char* src, int nargs, Oid* argtypes, parse_query_func parser = raw_parser);
extern SPIPlanPtr SPI_prepare_cursor(const char* src, int nargs, Oid* argtypes, int cursorOptions, parse_query_func parser = raw_parser);
extern SPIPlanPtr SPI_prepare_params(const char* src, ParserSetupHook parserSetup, void* parserSetupArg, int cursorOptions, parse_query_func parser = raw_parser);
extern int SPI_keepplan(SPIPlanPtr plan);
extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan);
extern int SPI_freeplan(SPIPlanPtr plan);
@ -125,7 +128,7 @@ extern void SPI_freetuptable(SPITupleTable* tuptable);
extern Portal SPI_cursor_open(const char* name, SPIPlanPtr plan, Datum* Values, const char* Nulls, bool read_only);
extern Portal SPI_cursor_open_with_args(const char* name, const char* src, int nargs, Oid* argtypes, Datum* Values,
const char* Nulls, bool read_only, int cursorOptions);
const char* Nulls, bool read_only, int cursorOptions, parse_query_func parser = raw_parser);
extern Portal SPI_cursor_open_with_paramlist(const char* name, SPIPlanPtr plan, ParamListInfo params,
bool read_only, bool isCollectParam = false);
extern Portal SPI_cursor_find(const char* name);
@ -152,23 +155,23 @@ extern DestReceiver* createAnalyzeSPIDestReceiver(CommandDest dest);
extern void ReleaseSpiPlanRef();
/* SPI execution helpers */
extern void spi_exec_with_callback(CommandDest dest, const char* src, bool read_only, long tcount, bool direct_call,
void (*callbackFn)(void*), void* clientData);
void (*callbackFn)(void*), void* clientData, parse_query_func parser = raw_parser);
extern void _SPI_error_callback(void *arg);
extern List* _SPI_get_querylist(SPIPlanPtr plan);
#ifdef PGXC
extern int SPI_execute_direct(const char* src, char* nodename);
extern int SPI_execute_direct(const char* src, char* nodename, parse_query_func parser = raw_parser);
#endif
extern int _SPI_begin_call(bool execmem);
extern int _SPI_end_call(bool procmem);
extern void _SPI_hold_cursor();
extern void _SPI_prepare_oneshot_plan_for_validator(const char* src, SPIPlanPtr plan);
extern void _SPI_prepare_oneshot_plan_for_validator(const char* src, SPIPlanPtr plan, parse_query_func parser = raw_parser);
extern void InitSPIPlanCxt();
extern void _SPI_prepare_plan(const char *src, SPIPlanPtr plan);
extern void _SPI_prepare_plan(const char *src, SPIPlanPtr plan, parse_query_func parser = raw_parser);
extern ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls,
Cursor_Data *cursor_data = NULL);
extern void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
extern void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan, parse_query_func parser = raw_parser);
extern int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot,
bool read_only, bool fire_triggers, long tcount, bool from_lock = false);

View File

@ -36,7 +36,8 @@ typedef enum {
LOGSTMT_ALL /* log all statements */
} LogStmtLevel;
extern List* pg_parse_query(const char* query_string, List** query_string_locationlist = NULL);
extern List* pg_parse_query(const char* query_string, List** query_string_locationlist = NULL,
List* (*parser_hook)(const char*, List**) = NULL);
extern List* pg_analyze_and_rewrite(Node* parsetree, const char* query_string, Oid* paramTypes, int numParams);
extern List* pg_analyze_and_rewrite_params(
Node* parsetree, const char* query_string, ParserSetupHook parserSetup, void* parserSetupArg);