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

Commit0d83ced

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 parentcb988b0 commit0d83ced

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
@@ -328,13 +328,13 @@ _SPI_rollback(bool chain)
328328
{
329329
MemoryContextoldcontext=CurrentMemoryContext;
330330

331-
/* seeunder SPI_commit() */
331+
/* seecomments in _SPI_commit() */
332332
if (_SPI_current->atomic)
333333
ereport(ERROR,
334334
(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
335335
errmsg("invalid transaction termination")));
336336

337-
/* seeunder SPI_commit() */
337+
/* seecomments in _SPI_commit() */
338338
if (IsSubTransaction())
339339
ereport(ERROR,
340340
(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
@@ -587,8 +587,11 @@ SPI_inside_nonatomic_context(void)
587587
{
588588
if (_SPI_current==NULL)
589589
return false;/* not in any SPI context at all */
590+
/* these tests must match _SPI_commit's opinion of what's atomic: */
590591
if (_SPI_current->atomic)
591592
return false;/* it's atomic (ie function not procedure) */
593+
if (IsSubTransaction())
594+
return false;/* if within subtransaction, it's atomic */
592595
return true;
593596
}
594597

@@ -2212,9 +2215,12 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
22122215

22132216
/*
22142217
* We allow nonatomic behavior only if plan->no_snapshots is set
2215-
* *and* the SPI_OPT_NONATOMIC flag was given when connecting.
2218+
* *and* the SPI_OPT_NONATOMIC flag was given when connecting and we are
2219+
* not inside a subtransaction. The latter two tests match whether
2220+
* _SPI_commit() would allow a commit; see there for more commentary.
22162221
*/
2217-
allow_nonatomic=plan->no_snapshots&& !_SPI_current->atomic;
2222+
allow_nonatomic=plan->no_snapshots&&
2223+
!_SPI_current->atomic&& !IsSubTransaction();
22182224

22192225
/*
22202226
* 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
@@ -490,6 +490,26 @@ NOTICE: f_get_x(1)
490490
NOTICE: f_print_x(1)
491491
NOTICE: f_get_x(2)
492492
NOTICE: f_print_x(2)
493+
-- test in non-atomic context, except exception block is locally atomic
494+
DO $$
495+
BEGIN
496+
BEGIN
497+
UPDATE t_test SET x = x + 1;
498+
RAISE NOTICE 'f_get_x(%)', f_get_x();
499+
CALL f_print_x(f_get_x());
500+
UPDATE t_test SET x = x + 1;
501+
RAISE NOTICE 'f_get_x(%)', f_get_x();
502+
CALL f_print_x(f_get_x());
503+
EXCEPTION WHEN division_by_zero THEN
504+
RAISE NOTICE '%', SQLERRM;
505+
END;
506+
ROLLBACK;
507+
END
508+
$$;
509+
NOTICE: f_get_x(1)
510+
NOTICE: f_print_x(1)
511+
NOTICE: f_get_x(2)
512+
NOTICE: f_print_x(2)
493513
-- test in atomic context
494514
BEGIN;
495515
DO $$

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,23 @@ BEGIN
460460
END
461461
$$;
462462

463+
-- test in non-atomic context, except exception block is locally atomic
464+
DO $$
465+
BEGIN
466+
BEGIN
467+
UPDATE t_testSET x= x+1;
468+
RAISE NOTICE'f_get_x(%)', f_get_x();
469+
CALL f_print_x(f_get_x());
470+
UPDATE t_testSET x= x+1;
471+
RAISE NOTICE'f_get_x(%)', f_get_x();
472+
CALL f_print_x(f_get_x());
473+
EXCEPTION WHEN division_by_zero THEN
474+
RAISE NOTICE'%', SQLERRM;
475+
END;
476+
ROLLBACK;
477+
END
478+
$$;
479+
463480
-- test in atomic context
464481
BEGIN;
465482

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp