Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2ad5f96

Browse files
committed
Fix misevaluation of STABLE parameters in CALL within plpgsql.
Before commit84f5c29, a STABLE function in a plpgsql CALLstatement's argument list would see an up-to-date snapshot,because exec_stmt_call would push a new snapshot. I got rid ofthat because the possibility of the snapshot disappearing withinCOMMIT made it too hard to manage a snapshot across the CALLstatement. That's fine so far as the procedure itself goes,but I forgot to think about the possibility of STABLE functionswithin the CALL argument list. As things now stand, those'llbe executed with the Portal's snapshot as ActiveSnapshot,keeping them from seeing updates more recent than Portal startup.(VOLATILE functions don't have a problem because they take theirown snapshots; which indeed is also why the procedure itselfdoesn't have a problem. There are no STABLE procedures.)We can fix this by pushing a new snapshot transiently withinExecuteCallStmt itself. Popping the snapshot before we getinto the procedure proper eliminates the management problem.The possibly-useless extra snapshot-grab is slightly annoying,but it's no worse than what happened before84f5c29.Per bug #17199 from Alexander Nawratil. Back-patch to v11,like the previous patch.Discussion:https://postgr.es/m/17199-1ab2561f0d94af92@postgresql.org
1 parentc1d1ae1 commit2ad5f96

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

‎src/backend/commands/functioncmds.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include"utils/lsyscache.h"
7474
#include"utils/memutils.h"
7575
#include"utils/rel.h"
76+
#include"utils/snapmgr.h"
7677
#include"utils/syscache.h"
7778
#include"utils/typcache.h"
7879

@@ -2273,6 +2274,16 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
22732274
estate->es_param_list_info=params;
22742275
econtext=CreateExprContext(estate);
22752276

2277+
/*
2278+
* If we're called in non-atomic context, we also have to ensure that the
2279+
* argument expressions run with an up-to-date snapshot. Our caller will
2280+
* have provided a current snapshot in atomic contexts, but not in
2281+
* non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2282+
* destroying the snapshot makes higher-level management too complicated.
2283+
*/
2284+
if (!atomic)
2285+
PushActiveSnapshot(GetTransactionSnapshot());
2286+
22762287
i=0;
22772288
foreach(lc,fexpr->args)
22782289
{
@@ -2290,20 +2301,23 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
22902301
i++;
22912302
}
22922303

2304+
/* Get rid of temporary snapshot for arguments, if we made one */
2305+
if (!atomic)
2306+
PopActiveSnapshot();
2307+
2308+
/* Here we actually call the procedure */
22932309
pgstat_init_function_usage(fcinfo,&fcusage);
22942310
retval=FunctionCallInvoke(fcinfo);
22952311
pgstat_end_function_usage(&fcusage, true);
22962312

2313+
/* Handle the procedure's outputs */
22972314
if (fexpr->funcresulttype==VOIDOID)
22982315
{
22992316
/* do nothing */
23002317
}
23012318
elseif (fexpr->funcresulttype==RECORDOID)
23022319
{
2303-
/*
2304-
* send tuple to client
2305-
*/
2306-
2320+
/* send tuple to client */
23072321
HeapTupleHeadertd;
23082322
OidtupType;
23092323
int32tupTypmod;

‎src/pl/plpgsql/src/expected/plpgsql_transaction.out

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,27 @@ SELECT * FROM test2;
600600
42
601601
(1 row)
602602

603+
-- another snapshot handling case: argument expressions of a CALL need
604+
-- to be evaluated with an up-to-date snapshot
605+
CREATE FUNCTION report_count() RETURNS int
606+
STABLE LANGUAGE sql
607+
AS $$ SELECT COUNT(*) FROM test2 $$;
608+
CREATE PROCEDURE transaction_test9b(cnt int)
609+
LANGUAGE plpgsql
610+
AS $$
611+
BEGIN
612+
RAISE NOTICE 'count = %', cnt;
613+
END
614+
$$;
615+
DO $$
616+
BEGIN
617+
CALL transaction_test9b(report_count());
618+
INSERT INTO test2 VALUES(43);
619+
CALL transaction_test9b(report_count());
620+
END
621+
$$;
622+
NOTICE: count = 1
623+
NOTICE: count = 2
603624
-- Test transaction in procedure with output parameters. This uses a
604625
-- different portal strategy and different code paths in pquery.c.
605626
CREATE PROCEDURE transaction_test10a(INOUT x int)

‎src/pl/plpgsql/src/sql/plpgsql_transaction.sql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,29 @@ $$;
507507
SELECT*FROM test2;
508508

509509

510+
-- another snapshot handling case: argument expressions of a CALL need
511+
-- to be evaluated with an up-to-date snapshot
512+
CREATEFUNCTIONreport_count() RETURNSint
513+
STABLE LANGUAGE sql
514+
AS $$SELECTCOUNT(*)FROM test2 $$;
515+
516+
CREATE PROCEDURE transaction_test9b(cntint)
517+
LANGUAGE plpgsql
518+
AS $$
519+
BEGIN
520+
RAISE NOTICE'count = %', cnt;
521+
END
522+
$$;
523+
524+
DO $$
525+
BEGIN
526+
CALL transaction_test9b(report_count());
527+
INSERT INTO test2VALUES(43);
528+
CALL transaction_test9b(report_count());
529+
END
530+
$$;
531+
532+
510533
-- Test transaction in procedure with output parameters. This uses a
511534
-- different portal strategy and different code paths in pquery.c.
512535
CREATE PROCEDURE transaction_test10a(INOUT xint)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp