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

Commit4476bcb

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 parentade24da commit4476bcb

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

@@ -2250,6 +2251,16 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
22502251
estate->es_param_list_info=params;
22512252
econtext=CreateExprContext(estate);
22522253

2254+
/*
2255+
* If we're called in non-atomic context, we also have to ensure that the
2256+
* argument expressions run with an up-to-date snapshot. Our caller will
2257+
* have provided a current snapshot in atomic contexts, but not in
2258+
* non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2259+
* destroying the snapshot makes higher-level management too complicated.
2260+
*/
2261+
if (!atomic)
2262+
PushActiveSnapshot(GetTransactionSnapshot());
2263+
22532264
i=0;
22542265
foreach(lc,fexpr->args)
22552266
{
@@ -2267,20 +2278,23 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
22672278
i++;
22682279
}
22692280

2281+
/* Get rid of temporary snapshot for arguments, if we made one */
2282+
if (!atomic)
2283+
PopActiveSnapshot();
2284+
2285+
/* Here we actually call the procedure */
22702286
pgstat_init_function_usage(fcinfo,&fcusage);
22712287
retval=FunctionCallInvoke(fcinfo);
22722288
pgstat_end_function_usage(&fcusage, true);
22732289

2290+
/* Handle the procedure's outputs */
22742291
if (fexpr->funcresulttype==VOIDOID)
22752292
{
22762293
/* do nothing */
22772294
}
22782295
elseif (fexpr->funcresulttype==RECORDOID)
22792296
{
2280-
/*
2281-
* send tuple to client
2282-
*/
2283-
2297+
/* send tuple to client */
22842298
HeapTupleHeadertd;
22852299
OidtupType;
22862300
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