!4114 修复ExecResult错误释放内存上下文的bug

Merge pull request !4114 from Cross-罗/fix_memory
This commit is contained in:
opengauss_bot
2023-09-12 11:26:17 +00:00
committed by Gitee
8 changed files with 72 additions and 15 deletions

View File

@ -11290,8 +11290,8 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict, int firstto
errmsg("Improper use of '.*'. The '.*' operator cannot be used with a row type variable."),
parser_errposition(yylloc)));
}
if (tok == T_DATUM || tok == T_VARRAY_VAR
|| tok == T_TABLE_VAR || tok == T_PACKAGE_VARIABLE) {
if (!DB_IS_CMPT(PG_FORMAT) && (tok == T_DATUM || tok == T_VARRAY_VAR
|| tok == T_TABLE_VAR || tok == T_PACKAGE_VARIABLE)) {
const char* message = "syntax error, expected \",\"";
InsertErrorMessage(message, plpgsql_yylloc);
ereport(errstate,
@ -11314,8 +11314,8 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict, int firstto
errmsg("record or row variable cannot be part of multiple-item INTO list"),
parser_errposition(yylloc)));
}
if (tok == T_DATUM || tok == T_VARRAY_VAR
|| tok == T_TABLE_VAR || tok == T_PACKAGE_VARIABLE) {
if (!DB_IS_CMPT(PG_FORMAT) && (tok == T_DATUM || tok == T_VARRAY_VAR
|| tok == T_TABLE_VAR || tok == T_PACKAGE_VARIABLE)) {
const char* message = "syntax error, expected \",\"";
InsertErrorMessage(message, plpgsql_yylloc);
ereport(errstate,
@ -11742,8 +11742,8 @@ read_into_array_table_scalar_list(char *initial_name,
}
}
if (tok == T_DATUM || tok == T_VARRAY_VAR
|| tok == T_TABLE_VAR || tok == T_PACKAGE_VARIABLE) {
if (!DB_IS_CMPT(PG_FORMAT) && (tok == T_DATUM || tok == T_VARRAY_VAR
|| tok == T_TABLE_VAR || tok == T_PACKAGE_VARIABLE)) {
const char* message = "syntax error, expected \",\"";
InsertErrorMessage(message, plpgsql_yylloc);
ereport(errstate,

View File

@ -1905,6 +1905,7 @@ static void init_fcache(
fcache->funcResultSlot = NULL;
fcache->setArgsValid = false;
fcache->shutdown_reg = false;
fcache->setArgByVal = false;
if(fcache->xprstate.is_flt_frame){
fcache->is_plpgsql_func_with_outparam = is_function_with_plpgsql_language_and_outparam(fcache->func.fn_oid);
fcache->has_refcursor = func_has_refcursor_args(fcache->func.fn_oid, &fcache->fcinfo_data);
@ -1936,6 +1937,7 @@ extern void ShutdownFuncExpr(Datum arg)
/* Clear any active set-argument state */
fcache->setArgsValid = false;
fcache->setArgByVal = false;
/* execUtils will deregister the callback... */
fcache->shutdown_reg = false;
@ -2188,6 +2190,16 @@ void set_result_for_plpgsql_language_function_with_outparam(FuncExprState *fcach
pfree(nulls);
}
bool ExecSetArgIsByValue(FunctionCallInfo fcinfo)
{
for (int i = 0; i < fcinfo->nargs; i++) {
if (!fcinfo->argnull[i] && !get_typbyval(fcinfo->argTypes[i])) {
return false;
}
}
return true;
}
/*
* ExecMakeFunctionResult
*
@ -2338,6 +2350,7 @@ restart:
} else {
hasSetArg = (argDone != ExprSingleResult);
}
fcache->setArgByVal = ExecSetArgIsByValue(fcinfo);
} else {
/* Re-use callinfo from previous evaluation */
hasSetArg = fcache->setHasSetArg;
@ -2497,6 +2510,10 @@ restart:
if (fcache->func.fn_retset && *isDone == ExprMultipleResult) {
fcache->setHasSetArg = hasSetArg;
fcache->setArgsValid = true;
/* arg not by value, memory can not be reset */
if (!fcache->setArgByVal) {
econtext->hasSetResultStore = true;
}
/* Register cleanup callback if we didn't already */
if (!fcache->shutdown_reg) {
RegisterExprContextCallback(econtext, ShutdownFuncExpr, PointerGetDatum(fcache));

View File

@ -91,13 +91,6 @@ static TupleTableSlot* ExecResult(PlanState* state)
}
}
/*
* Reset per-tuple memory context to free any expression evaluation
* storage allocated in the previous tuple cycle. Note this can't happen
* until we're done projecting out tuples from a scan tuple.
*/
ResetExprContext(econtext);
/*
* Reset per-tuple memory context to free any expression evaluation
* storage allocated in the previous tuple cycle. Note this can't happen
@ -124,7 +117,8 @@ static TupleTableSlot* ExecResult(PlanState* state)
if (econtext->hasSetResultStore) {
/* return values all store in ResultStore, could not free early one */
ResetExprContext(econtext);
econtext->hasSetResultStore = false;
}
/*

View File

@ -246,6 +246,7 @@ extern void EvalPlanQualFetchRowMarksUHeap(EPQState* epqstate);
extern TupleTableSlot* EvalPlanQualNext(EPQState* epqstate);
extern void EvalPlanQualBegin(EPQState* epqstate, EState* parentestate, bool isUHeap = false);
extern void EvalPlanQualEnd(EPQState* epqstate);
extern bool ExecSetArgIsByValue(FunctionCallInfoData* fcinfo);
/*
* functions in execProcnode.c

View File

@ -964,6 +964,8 @@ typedef struct FuncExprState {
*/
bool setArgsValid;
bool setArgByVal; /* all args are by val? */
bool setHasSetArg;
bool is_plpgsql_func_with_outparam;

View File

@ -0,0 +1,24 @@
drop schema if exists orafce cascade;
NOTICE: schema "orafce" does not exist, skipping
create schema orafce;
CREATE OR REPLACE FUNCTION orafce.regexp_substr(text, text, integer, integer, text, int)
RETURNS text
AS $$
DECLARE
v_substr text;
v_pattern text := $2;
modifiers text := $5;
v_subexpr integer := $6;
has_group integer := 2;
BEGIN
v_substr := (SELECT (regexp_matches(substr($1, $3), v_pattern, modifiers))[v_subexpr] OFFSET $4 - 1 LIMIT 1);
RETURN v_substr;
END;
$$
LANGUAGE plpgsql;
SELECT orafce.REGEXP_SUBSTR('1234567890 1234557890', '(123)(4(5[56])(78))', 1, 2, 'i', 3);
regexp_substr
---------------
(1 row)

View File

@ -29,7 +29,7 @@ test: replace_func_with_two_args trunc_func_for_date nlssort_pinyin updatable_vi
# test multiple statistics
test: functional_dependency
test: pg_proc_test test_row_type_in_proc
test: pg_proc_test test_row_type_in_proc exec_result_test
# test fdw
# NOTICE: In the "fdw_prepare", we copy the fdw test to be used from contrib into regress sql set.

View File

@ -0,0 +1,19 @@
drop schema if exists orafce cascade;
create schema orafce;
CREATE OR REPLACE FUNCTION orafce.regexp_substr(text, text, integer, integer, text, int)
RETURNS text
AS $$
DECLARE
v_substr text;
v_pattern text := $2;
modifiers text := $5;
v_subexpr integer := $6;
has_group integer := 2;
BEGIN
v_substr := (SELECT (regexp_matches(substr($1, $3), v_pattern, modifiers))[v_subexpr] OFFSET $4 - 1 LIMIT 1);
RETURN v_substr;
END;
$$
LANGUAGE plpgsql;
SELECT orafce.REGEXP_SUBSTR('1234567890 1234557890', '(123)(4(5[56])(78))', 1, 2, 'i', 3);