From 0ea25ed108d8344ac17012e62790e7e9ef7f1a7a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 28 Dec 2020 11:41:25 -0500 Subject: [PATCH] Fix thinko in plpgsql memory leak fix. Commit a6b1f5365 intended to place the transient "target" list of a CALL statement in the function's statement-lifespan context, but I fat-fingered that and used get_eval_mcontext() instead of get_stmt_mcontext(). The eval_mcontext belongs to the "simple expression" infrastructure, which is destroyed at transaction end. The net effect is that a CALL in a procedure to another procedure that has OUT or INOUT parameters would fail if the called procedure did a COMMIT. Per report from Peter Eisentraut. Back-patch to v11, like the prior patch. Discussion: https://postgr.es/m/f075f7be-c654-9aa8-3ffc-e9214622f02a@enterprisedb.com --- src/pl/plpgsql/src/expected/plpgsql_call.out | 21 +++++++++++++++++ src/pl/plpgsql/src/pl_exec.c | 4 ++-- src/pl/plpgsql/src/sql/plpgsql_call.sql | 24 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/pl/plpgsql/src/expected/plpgsql_call.out b/src/pl/plpgsql/src/expected/plpgsql_call.out index d9c88e85c8..fbe8a04606 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_call.out +++ b/src/pl/plpgsql/src/expected/plpgsql_call.out @@ -152,6 +152,27 @@ CALL test_proc7(100, -1, -1); 0 | 1 (1 row) +-- inner COMMIT with output arguments +CREATE PROCEDURE test_proc7c(x int, INOUT a int, INOUT b numeric) +LANGUAGE plpgsql +AS $$ +BEGIN + a := x / 10; + b := x / 2; + COMMIT; +END; +$$; +CREATE PROCEDURE test_proc7cc(_x int) +LANGUAGE plpgsql +AS $$ +DECLARE _a int; _b numeric; +BEGIN + CALL test_proc7c(_x, _a, _b); + RAISE NOTICE '_x: %,_a: %, _b: %', _x, _a, _b; +END +$$; +CALL test_proc7cc(10); +NOTICE: _x: 10,_a: 1, _b: 5 -- named parameters and defaults CREATE PROCEDURE test_proc8a(INOUT a int, INOUT b int) LANGUAGE plpgsql diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index ea134ba72e..462ce4d170 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -2224,8 +2224,8 @@ exec_stmt_call(PLpgSQL_execstate *estate, PLpgSQL_stmt_call *stmt) int i; ListCell *lc; - /* Use eval_mcontext for any cruft accumulated here */ - oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate)); + /* Use stmt_mcontext for any cruft accumulated here */ + oldcontext = MemoryContextSwitchTo(get_stmt_mcontext(estate)); /* * Get the parsed CallStmt, and look up the called procedure diff --git a/src/pl/plpgsql/src/sql/plpgsql_call.sql b/src/pl/plpgsql/src/sql/plpgsql_call.sql index 4702bd14d1..21b4a37e59 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_call.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_call.sql @@ -141,6 +141,30 @@ $$; CALL test_proc7(100, -1, -1); +-- inner COMMIT with output arguments + +CREATE PROCEDURE test_proc7c(x int, INOUT a int, INOUT b numeric) +LANGUAGE plpgsql +AS $$ +BEGIN + a := x / 10; + b := x / 2; + COMMIT; +END; +$$; + +CREATE PROCEDURE test_proc7cc(_x int) +LANGUAGE plpgsql +AS $$ +DECLARE _a int; _b numeric; +BEGIN + CALL test_proc7c(_x, _a, _b); + RAISE NOTICE '_x: %,_a: %, _b: %', _x, _a, _b; +END +$$; + +CALL test_proc7cc(10); + -- named parameters and defaults