From d1670f067703d4b65aef94cfc3903be675ba7663 Mon Sep 17 00:00:00 2001 From: Parikshit Sarode Date: Sun, 8 Oct 2023 10:20:15 +0000 Subject: [PATCH] changes reverted --- contrib/babelfishpg_tsql/src/pl_exec.c | 223 ++++--------------------- 1 file changed, 37 insertions(+), 186 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/pl_exec.c b/contrib/babelfishpg_tsql/src/pl_exec.c index 37edb58353..188d0fbc16 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec.c +++ b/contrib/babelfishpg_tsql/src/pl_exec.c @@ -15,35 +15,10 @@ #include "postgres.h" -#include "utils/hsearch.h" -#include "utils/lsyscache.h" -#include "utils/syscache.h" -#include "utils/memutils.h" -#include "utils/builtins.h" -#include "catalog/pg_type.h" -#include "catalog/pg_collation.h" -#include "catalog/namespace.h" -#include "catalog/pg_trigger.h" -#include "tsearch/ts_locale.h" -#include "nodes/makefuncs.h" - -#include "collation.h" #include #include "access/detoast.h" #include "access/htup_details.h" -#include -#include "nodes/parsenodes.h" -#include "parser/parser.h" -#include "parser/scansup.h" -#include "libpq/pqformat.h" -#include "utils/memutils.h" -#include "pltsql.h" -#include "pltsql-2.h" -#include "pltsql_instr.h" -#include "utils/builtins.h" -#include "utils/numeric.h" -#include "utils/syscache.h" #include "access/printtup.h" #include "access/transam.h" #include "access/tupconvert.h" @@ -62,7 +37,6 @@ #include "parser/parser.h" /* only needed for GUC variables */ #include "parser/parse_coerce.h" #include "parser/parse_type.h" -#include "utils/hsearch.h" #include "parser/scansup.h" #include "storage/proc.h" #include "tcop/pquery.h" @@ -79,7 +53,7 @@ #include "utils/snapmgr.h" #include "utils/syscache.h" #include "utils/typcache.h" -#include "hooks.h" + #include "pltsql.h" #include "access/xact.h" #include "err_handler.h" @@ -139,7 +113,6 @@ typedef struct SimpleEcontextStackEntry static EState *shared_simple_eval_estate = NULL; static SimpleEcontextStackEntry *simple_econtext_stack = NULL; -static ResourceOwner shared_simple_eval_resowner = NULL; /* * Memory management within a pltsql function generally works with three @@ -361,8 +334,7 @@ static int exec_stmt_set(PLtsql_execstate *estate, void pltsql_estate_setup(PLtsql_execstate *estate, PLtsql_function *func, ReturnSetInfo *rsi, - EState *simple_eval_estate, - ResourceOwner simple_eval_resowner); + EState *simple_eval_estate); void exec_eval_cleanup(PLtsql_execstate *estate); int exec_fmtonly(PLtsql_execstate *estate, @@ -527,7 +499,7 @@ extern int */ Datum pltsql_exec_function(PLtsql_function *func, FunctionCallInfo fcinfo, - EState *simple_eval_estate, ResourceOwner simple_eval_resowner, bool atomic) + EState *simple_eval_estate, bool atomic) { PLtsql_execstate estate; ErrorContextCallback plerrcontext; @@ -538,7 +510,7 @@ pltsql_exec_function(PLtsql_function *func, FunctionCallInfo fcinfo, * Setup the execution state */ pltsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo, - simple_eval_estate,simple_eval_resowner); + simple_eval_estate); estate.atomic = atomic; /* @@ -1082,7 +1054,7 @@ pltsql_exec_trigger(PLtsql_function *func, /* * Setup the execution state */ - pltsql_estate_setup(&estate, func, NULL, NULL, NULL); + pltsql_estate_setup(&estate, func, NULL, NULL); if (pltsql_support_tsql_transactions() && !pltsql_disable_txn_in_triggers) estate.atomic = false; @@ -1364,7 +1336,7 @@ pltsql_exec_event_trigger(PLtsql_function *func, EventTriggerData *trigdata) /* * Setup the execution state */ - pltsql_estate_setup(&estate, func, NULL, NULL, NULL); + pltsql_estate_setup(&estate, func, NULL, NULL); estate.evtrigdata = trigdata; /* @@ -2607,7 +2579,6 @@ exec_stmt_call(PLtsql_execstate *estate, PLtsql_stmt_call *stmt) * some internal state. */ estate->simple_eval_estate = NULL; - estate->simple_eval_resowner = NULL; pltsql_create_econtext(estate); } @@ -4246,8 +4217,7 @@ void pltsql_estate_setup(PLtsql_execstate *estate, PLtsql_function *func, ReturnSetInfo *rsi, - EState *simple_eval_estate, - ResourceOwner simple_eval_resowner) + EState *simple_eval_estate) { HASHCTL ctl; PLExecStateCallStack *es_cs_entry; @@ -4349,11 +4319,6 @@ pltsql_estate_setup(PLtsql_execstate *estate, estate->cast_hash = shared_cast_hash; estate->cast_hash_context = shared_cast_context; } - /* likewise for the simple-expression resource owner */ - if (simple_eval_resowner) - estate->simple_eval_resowner = simple_eval_resowner; - else - estate->simple_eval_resowner = shared_simple_eval_resowner; /* * We start with no stmt_mcontext; one will be created only if needed. @@ -4492,10 +4457,7 @@ commit_stmt(PLtsql_execstate *estate, bool txnStarted) * transactions do not affect it */ if (estate->use_shared_simple_eval_state && simple_econtext_stack == NULL) - { estate->simple_eval_estate = NULL; - estate->simple_eval_resowner = NULL; - } /* * simple_econtext_stack being NULL only reliably identifies @@ -4644,7 +4606,6 @@ is_impl_txn_required_for_execsql(PLtsql_stmt_execsql *stmt) * needs to use that, fix those callers to push/pop stmt_mcontext. * ---------- */ - static int exec_stmt_execsql(PLtsql_execstate *estate, PLtsql_stmt_execsql *stmt) @@ -5465,10 +5426,7 @@ exec_fmtonly(PLtsql_execstate *estate, * simple-expression infrastructure. */ if (estate->use_shared_simple_eval_state) - { estate->simple_eval_estate = NULL; - estate->simple_eval_resowner = NULL; - } pltsql_create_econtext(estate); } @@ -6258,11 +6216,7 @@ exec_stmt_commit(PLtsql_execstate *estate, PLtsql_stmt_commit *stmt) SPI_commit(); SPI_start_transaction(); - if (estate->use_shared_simple_eval_state) - { - estate->simple_eval_estate = NULL; - estate->simple_eval_resowner = NULL; - } + estate->simple_eval_estate = NULL; pltsql_create_econtext(estate); return PLTSQL_RC_OK; @@ -6279,11 +6233,7 @@ exec_stmt_rollback(PLtsql_execstate *estate, PLtsql_stmt_rollback *stmt) SPI_rollback(); SPI_start_transaction(); - if (estate->use_shared_simple_eval_state) - { - estate->simple_eval_estate = NULL; - estate->simple_eval_resowner = NULL; - } + estate->simple_eval_estate = NULL; pltsql_create_econtext(estate); return PLTSQL_RC_OK; @@ -6326,12 +6276,6 @@ exec_stmt_set(PLtsql_execstate *estate, PLtsql_stmt_set *stmt) * exec_assign_expr Put an expression's result into a variable. * ---------- */ -// bool prev_isnull; -// Datum prev_value; -// PLtsql_execstate *prev_estate; -// PLtsql_expr *prev_expr; -// Oid prev_valtype; -// int32 prev_valtypmod; static void exec_assign_expr(PLtsql_execstate *estate, PLtsql_datum *target, PLtsql_expr *expr) @@ -6385,7 +6329,7 @@ exec_assign_expr(PLtsql_execstate *estate, PLtsql_datum *target, } value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod); - + /* * Unlike other scenario using implicit castings to (var)char, (i.e. * insert into table) SET statement should suppress data truncation error. @@ -7590,7 +7534,6 @@ exec_for_query(PLtsql_execstate *estate, PLtsql_stmt_forq *stmt, * It will be freed when exec_eval_cleanup is done. * ---------- */ - static bool exec_eval_simple_expr(PLtsql_execstate *estate, PLtsql_expr *expr, @@ -7601,7 +7544,7 @@ exec_eval_simple_expr(PLtsql_execstate *estate, { ExprContext *econtext = estate->eval_econtext; LocalTransactionId curlxid = MyProc->lxid; - ParamListInfo paramLI; + CachedPlan *cplan; void *save_setup_arg; bool need_snapshot; MemoryContext oldcontext; @@ -7615,8 +7558,7 @@ exec_eval_simple_expr(PLtsql_execstate *estate, /* * If expression is in use in current xact, don't touch it. */ - if (unlikely(expr->expr_simple_in_use) && - expr->expr_simple_lxid == curlxid) + if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid) return false; /* @@ -7629,84 +7571,24 @@ exec_eval_simple_expr(PLtsql_execstate *estate, EnsurePortalSnapshotExists(); /* - * Check to see if the cached plan has been invalidated. If not, and this - * is the first use in the current transaction, save a plan refcount in - * the simple-expression resowner. + * Revalidate cached plan, so that we will notice if it became stale. (We + * need to hold a refcount while using the plan, anyway.) If replanning + * is needed, do that work in the eval_mcontext. */ - if (likely(CachedPlanIsSimplyValid(expr->expr_simple_plansource, - expr->expr_simple_plan, - (expr->expr_simple_plan_lxid != curlxid ? - estate->simple_eval_resowner : NULL)))) - { - /* - * It's still good, so just remember that we have a refcount on the - * plan in the current transaction. (If we already had one, this - * assignment is a no-op.) - */ - expr->expr_simple_plan_lxid = curlxid; - } - else - { - /* Need to replan */ - CachedPlan *cplan; - - /* - * If we have a valid refcount on some previous version of the plan, - * release it, so we don't leak plans intra-transaction. - */ - if (expr->expr_simple_plan_lxid == curlxid) - { - ResourceOwner saveResourceOwner = CurrentResourceOwner; - - CurrentResourceOwner = estate->simple_eval_resowner; - ReleaseCachedPlan(expr->expr_simple_plan, CurrentResourceOwner); - CurrentResourceOwner = saveResourceOwner; - expr->expr_simple_plan = NULL; - expr->expr_simple_plan_lxid = InvalidLocalTransactionId; - } - /* Do the replanning work in the eval_mcontext */ - oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate)); - cplan = SPI_plan_get_cached_plan(expr->plan); - MemoryContextSwitchTo(oldcontext); - - /* - * We can't get a failure here, because the number of - * CachedPlanSources in the SPI plan can't change from what - * exec_simple_check_plan saw; it's a property of the raw parsetree - * generated from the query text. - */ - Assert(cplan != NULL); - /* - * These tests probably can't fail either, but if they do, cope by - * declaring the plan to be non-simple. On success, we'll acquire a - * refcount on the new plan, stored in simple_eval_resowner. - */ - if (CachedPlanAllowsSimpleValidityCheck(expr->expr_simple_plansource, - cplan) && - CachedPlanIsSimplyValid(expr->expr_simple_plansource, cplan, - estate->simple_eval_resowner)) - { - /* Remember that we have the refcount */ - expr->expr_simple_plan = cplan; - expr->expr_simple_plan_lxid = curlxid; - } - else - { - /* Release SPI_plan_get_cached_plan's refcount */ - ReleaseCachedPlan(cplan, CurrentResourceOwner); - /* Mark expression as non-simple, and fail */ - expr->expr_simple_expr = NULL; - return false; - } + oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate)); + cplan = SPI_plan_get_cached_plan(expr->plan); + MemoryContextSwitchTo(oldcontext); - /* - * SPI_plan_get_cached_plan acquired a plan refcount stored in the - * active resowner. We don't need that anymore, so release it. - */ - ReleaseCachedPlan(cplan, CurrentResourceOwner); + /* + * We can't get a failure here, because the number of CachedPlanSources in + * the SPI plan can't change from what exec_simple_check_plan saw; it's a + * property of the raw parsetree generated from the query text. + */ + Assert(cplan != NULL); - /* Extract desired scalar expression from cached plan */ - + /* If it got replanned, update our copy of the simple expression */ + if (cplan->generation != expr->expr_simple_generation) + { exec_save_simple_expr(expr, cplan); /* better recheck r/w safety, as it could change due to inlining */ if (expr->rwparam >= 0) @@ -7723,16 +7605,9 @@ exec_eval_simple_expr(PLtsql_execstate *estate, * Set up ParamListInfo to pass to executor. For safety, save and restore * estate->paramLI->parserSetupArg around our use of the param list. */ - paramLI = estate->paramLI; - save_setup_arg = paramLI->parserSetupArg; - /* - * We can skip using setup_param_list() in favor of just doing this - * unconditionally, because there's no need for the optimization of - * possibly setting ecxt_param_list_info to NULL; we've already forced use - * of a generic plan. - */ - paramLI->parserSetupArg = (void *) expr; - econtext->ecxt_param_list_info = paramLI; + save_setup_arg = estate->paramLI->parserSetupArg; + + econtext->ecxt_param_list_info = setup_param_list(estate, expr); /* * Prepare the expression for execution, if it's not been done already in @@ -7742,7 +7617,7 @@ exec_eval_simple_expr(PLtsql_execstate *estate, * commit/rollback. There is still leak when it is Top level batch + * replan and needs fix. */ - if (unlikely(expr->expr_simple_lxid != curlxid) && (expr->expr_simple_state == NULL || estate->use_shared_simple_eval_state)) + if (expr->expr_simple_lxid != curlxid && (expr->expr_simple_state == NULL || estate->use_shared_simple_eval_state)) { oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt); expr->expr_simple_state = @@ -7790,13 +7665,18 @@ exec_eval_simple_expr(PLtsql_execstate *estate, econtext->ecxt_param_list_info = NULL; - paramLI->parserSetupArg = save_setup_arg; + estate->paramLI->parserSetupArg = save_setup_arg; if (need_snapshot) PopActiveSnapshot(); MemoryContextSwitchTo(oldcontext); + /* + * Now we can release our refcount on the cached plan. + */ + ReleaseCachedPlan(cplan, CurrentResourceOwner); + /* * That's it. */ @@ -9614,17 +9494,6 @@ pltsql_create_econtext(PLtsql_execstate *estate) } estate->simple_eval_estate = shared_simple_eval_estate; } - /* - * Likewise for the simple-expression resource owner. - */ - if (estate->simple_eval_resowner == NULL) - { - if (shared_simple_eval_resowner == NULL) - shared_simple_eval_resowner = - ResourceOwnerCreate(TopTransactionResourceOwner, - "PLTSQL simple expressions"); - estate->simple_eval_resowner = shared_simple_eval_resowner; - } /* * Create a child econtext for the current function. @@ -9673,10 +9542,7 @@ pltsql_commit_not_required_impl_txn(PLtsql_execstate *estate) MemoryContextSwitchTo(cur_ctxt); if (estate->use_shared_simple_eval_state) - { estate->simple_eval_estate = NULL; - estate->simple_eval_resowner = NULL; - } pltsql_create_econtext(estate); } @@ -9803,30 +9669,15 @@ pltsql_xact_cb(XactEvent event, void *arg) * any remaining resources will be released correctly). In an abort, we * expect the regular abort recovery procedures to release everything of * interest. - * * If we are doing a clean transaction shutdown, free the EState and tell - * the resowner to release whatever plancache references it has, so that - * all remaining resources will be released correctly. (We don't need to - * actually delete the resowner here; deletion of the - * TopTransactionResourceOwner will take care of that.) - * - * In an abort, we expect the regular abort recovery procedures to release - * everything of interest, so just clear our pointers. */ if (event == XACT_EVENT_COMMIT || event == XACT_EVENT_PREPARE) { txn_clean_estate(true); - if (shared_simple_eval_estate) - FreeExecutorState(shared_simple_eval_estate); - shared_simple_eval_estate = NULL; - if (shared_simple_eval_resowner) - ResourceOwnerReleaseAllPlanCacheRefs(shared_simple_eval_resowner); - shared_simple_eval_resowner = NULL; } else if (event == XACT_EVENT_ABORT) { simple_econtext_stack = NULL; shared_simple_eval_estate = NULL; - shared_simple_eval_resowner = NULL; } /* Reset portal snapshot in case of commit/rollback */ if (pltsql_snapshot_portal != NULL)