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

Commit25d639e

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 parent05e982c commit25d639e

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
@@ -335,13 +335,13 @@ _SPI_rollback(bool chain)
335335
MemoryContextoldcontext=CurrentMemoryContext;
336336
SavedTransactionCharacteristicssavetc;
337337

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

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

@@ -2410,9 +2413,12 @@ _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options,
24102413

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

24172423
/*
24182424
* 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