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

Commitb5eef75

Browse files
committed
Further refine _SPI_execute_plan's rule for atomic execution.
Commit2dc1dea turns out to have been still a brick shy of a load,because CALL statements executing within a plpgsql exception blockcould still pass the wrong snapshot to stable functions within theCALL's argument list. That happened because standard_ProcessUtilityforces isAtomicContext to true if IsTransactionBlock is true, whichit always will be inside a subtransaction. Then ExecuteCallStmtwould think it does not need to push a new snapshot --- but_SPI_execute_plan didn't do so either, since it thought it was innonatomic mode.The best fix for this seems to be for _SPI_execute_plan to operatein atomic execution mode if IsSubTransaction() is true, even when theSPI context as a whole is non-atomic. This makes _SPI_execute_planhave the same rules about when non-atomic execution is allowed as_SPI_commit/_SPI_rollback have about when COMMIT/ROLLBACK are allowed,which seems appropriately symmetric. (If anyone ever tries to allowCOMMIT/ROLLBACK inside a subtransaction, this would all need to berethought ... but I'm unconvinced that such a thing could be logicallyconsistent at all.)For further consistency, also check IsSubTransaction() inSPI_inside_nonatomic_context. That does not matter for itsone present-day caller StartTransaction, which can't be reachedinside a subtransaction. But if any other callers ever arise,they'd presumably want this definition.Per bug #18656 from Alexander Alehin. Back-patch to allsupported branches, like previous fixes in this area.Discussion:https://postgr.es/m/18656-cade1780866ef66c@postgresql.org
1 parenteef9cc4 commitb5eef75

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

‎src/backend/executor/spi.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,13 @@ _SPI_rollback(bool chain)
334334
MemoryContextoldcontext=CurrentMemoryContext;
335335
SavedTransactionCharacteristicssavetc;
336336

337-
/* seeunder SPI_commit() */
337+
/* seecomments in _SPI_commit() */
338338
if (_SPI_current->atomic)
339339
ereport(ERROR,
340340
(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
341341
errmsg("invalid transaction termination")));
342342

343-
/* seeunder SPI_commit() */
343+
/* seecomments in _SPI_commit() */
344344
if (IsSubTransaction())
345345
ereport(ERROR,
346346
(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
@@ -582,8 +582,11 @@ SPI_inside_nonatomic_context(void)
582582
{
583583
if (_SPI_current==NULL)
584584
return false;/* not in any SPI context at all */
585+
/* these tests must match _SPI_commit's opinion of what's atomic: */
585586
if (_SPI_current->atomic)
586587
return false;/* it's atomic (ie function not procedure) */
588+
if (IsSubTransaction())
589+
return false;/* if within subtransaction, it's atomic */
587590
return true;
588591
}
589592

@@ -2411,9 +2414,12 @@ _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options,
24112414

24122415
/*
24132416
* We allow nonatomic behavior only if options->allow_nonatomic is set
2414-
* *and* the SPI_OPT_NONATOMIC flag was given when connecting.
2417+
* *and* the SPI_OPT_NONATOMIC flag was given when connecting and we are
2418+
* not inside a subtransaction. The latter two tests match whether
2419+
* _SPI_commit() would allow a commit; see there for more commentary.
24152420
*/
2416-
allow_nonatomic=options->allow_nonatomic&& !_SPI_current->atomic;
2421+
allow_nonatomic=options->allow_nonatomic&&
2422+
!_SPI_current->atomic&& !IsSubTransaction();
24172423

24182424
/*
24192425
* Setup error traceback support for ereport()

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,26 @@ NOTICE: f_get_x(1)
597597
NOTICE: f_print_x(1)
598598
NOTICE: f_get_x(2)
599599
NOTICE: f_print_x(2)
600+
-- test in non-atomic context, except exception block is locally atomic
601+
DO $$
602+
BEGIN
603+
BEGIN
604+
UPDATE t_test SET x = x + 1;
605+
RAISE NOTICE 'f_get_x(%)', f_get_x();
606+
CALL f_print_x(f_get_x());
607+
UPDATE t_test SET x = x + 1;
608+
RAISE NOTICE 'f_get_x(%)', f_get_x();
609+
CALL f_print_x(f_get_x());
610+
EXCEPTION WHEN division_by_zero THEN
611+
RAISE NOTICE '%', SQLERRM;
612+
END;
613+
ROLLBACK;
614+
END
615+
$$;
616+
NOTICE: f_get_x(1)
617+
NOTICE: f_print_x(1)
618+
NOTICE: f_get_x(2)
619+
NOTICE: f_print_x(2)
600620
-- test in atomic context
601621
BEGIN;
602622
DO $$

‎src/pl/plpgsql/src/sql/plpgsql_call.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,23 @@ BEGIN
557557
END
558558
$$;
559559

560+
-- test in non-atomic context, except exception block is locally atomic
561+
DO $$
562+
BEGIN
563+
BEGIN
564+
UPDATE t_testSET x= x+1;
565+
RAISE NOTICE'f_get_x(%)', f_get_x();
566+
CALL f_print_x(f_get_x());
567+
UPDATE t_testSET x= x+1;
568+
RAISE NOTICE'f_get_x(%)', f_get_x();
569+
CALL f_print_x(f_get_x());
570+
EXCEPTION WHEN division_by_zero THEN
571+
RAISE NOTICE'%', SQLERRM;
572+
END;
573+
ROLLBACK;
574+
END
575+
$$;
576+
560577
-- test in atomic context
561578
BEGIN;
562579

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp