@@ -346,8 +346,8 @@ static void CommitTransaction(void);
346346static TransactionId RecordTransactionAbort (bool isSubXact );
347347static void StartTransaction (void );
348348
349- static void CommitTransactionCommandInternal (void );
350- static void AbortCurrentTransactionInternal (void );
349+ static bool CommitTransactionCommandInternal (void );
350+ static bool AbortCurrentTransactionInternal (void );
351351
352352static void StartSubTransaction (void );
353353static void CommitSubTransaction (void );
@@ -3092,50 +3092,27 @@ RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
30923092void
30933093CommitTransactionCommand (void )
30943094{
3095- while (true)
3095+ /*
3096+ * Repeatedly call CommitTransactionCommandInternal() until all the work
3097+ * is done.
3098+ */
3099+ while (!CommitTransactionCommandInternal ())
30963100 {
3097- switch (CurrentTransactionState -> blockState )
3098- {
3099- /*
3100- * The current already-failed subtransaction is ending due to
3101- * a ROLLBACK or ROLLBACK TO command, so pop it and
3102- * recursively examine the parent (which could be in any of
3103- * several states).
3104- */
3105- case TBLOCK_SUBABORT_END :
3106- CleanupSubTransaction ();
3107- continue ;
3108-
3109- /*
3110- * As above, but it's not dead yet, so abort first.
3111- */
3112- case TBLOCK_SUBABORT_PENDING :
3113- AbortSubTransaction ();
3114- CleanupSubTransaction ();
3115- continue ;
3116- default :
3117- break ;
3118- }
3119- CommitTransactionCommandInternal ();
3120- break ;
31213101 }
31223102}
31233103
31243104/*
3125- * CommitTransactionCommandInternal - a function doing all the material work
3126- * regarding handling the commit transaction command except for loop over
3127- * subtransactions.
3105+ * CommitTransactionCommandInternal - a function doing an iteration of work
3106+ * regarding handling the commit transaction command. In the case of
3107+ * subtransactions more than one iterations could be required. Returns
3108+ * true when no more iterations required, false otherwise.
31283109 */
3129- static void
3110+ static bool
31303111CommitTransactionCommandInternal (void )
31313112{
31323113 TransactionState s = CurrentTransactionState ;
31333114 SavedTransactionCharacteristics savetc ;
31343115
3135- /* This states are handled in CommitTransactionCommand() */
3136- Assert (s -> blockState != TBLOCK_SUBABORT_END &&
3137- s -> blockState != TBLOCK_SUBABORT_PENDING );
3138-
31393116 /* Must save in case we need to restore below */
31403117 SaveTransactionCharacteristics (& savetc );
31413118
@@ -3319,6 +3296,25 @@ CommitTransactionCommandInternal(void)
33193296 BlockStateAsString (s -> blockState ));
33203297 break ;
33213298
3299+ /*
3300+ * The current already-failed subtransaction is ending due to a
3301+ * ROLLBACK or ROLLBACK TO command, so pop it and recursively
3302+ * examine the parent (which could be in any of several states).
3303+ * As we need to examine the parent, return false to request the
3304+ * caller to do the next iteration.
3305+ */
3306+ case TBLOCK_SUBABORT_END :
3307+ CleanupSubTransaction ();
3308+ return false;
3309+
3310+ /*
3311+ * As above, but it's not dead yet, so abort first.
3312+ */
3313+ case TBLOCK_SUBABORT_PENDING :
3314+ AbortSubTransaction ();
3315+ CleanupSubTransaction ();
3316+ return false;
3317+
33223318 /*
33233319 * The current subtransaction is the target of a ROLLBACK TO
33243320 * command. Abort and pop it, then start a new subtransaction
@@ -3376,10 +3372,10 @@ CommitTransactionCommandInternal(void)
33763372 s -> blockState = TBLOCK_SUBINPROGRESS ;
33773373 }
33783374 break ;
3379- default :
3380- /* Keep compiler quiet */
3381- break ;
33823375 }
3376+
3377+ /* Done, no more iterations required */
3378+ return true;
33833379}
33843380
33853381/*
@@ -3390,59 +3386,26 @@ CommitTransactionCommandInternal(void)
33903386void
33913387AbortCurrentTransaction (void )
33923388{
3393- while (true)
3389+ /*
3390+ * Repeatedly call AbortCurrentTransactionInternal() until all the work is
3391+ * done.
3392+ */
3393+ while (!AbortCurrentTransactionInternal ())
33943394 {
3395- switch (CurrentTransactionState -> blockState )
3396- {
3397- /*
3398- * If we failed while trying to create a subtransaction, clean
3399- * up the broken subtransaction and abort the parent. The
3400- * same applies if we get a failure while ending a
3401- * subtransaction.
3402- */
3403- case TBLOCK_SUBBEGIN :
3404- case TBLOCK_SUBRELEASE :
3405- case TBLOCK_SUBCOMMIT :
3406- case TBLOCK_SUBABORT_PENDING :
3407- case TBLOCK_SUBRESTART :
3408- AbortSubTransaction ();
3409- CleanupSubTransaction ();
3410- continue ;
3411-
3412- /*
3413- * Same as above, except the Abort() was already done.
3414- */
3415- case TBLOCK_SUBABORT_END :
3416- case TBLOCK_SUBABORT_RESTART :
3417- CleanupSubTransaction ();
3418- continue ;
3419- default :
3420- break ;
3421- }
3422- AbortCurrentTransactionInternal ();
3423- break ;
34243395 }
34253396}
34263397
34273398/*
3428- * AbortCurrentTransactionInternal - a function doing all the material work
3429- * regarding handling the abort transaction command except for loop over
3430- * subtransactions.
3399+ * AbortCurrentTransactionInternal - a function doing an iteration of work
3400+ * regarding handling the current transaction abort. In the case of
3401+ * subtransactions more than one iterations could be required. Returns
3402+ * true when no more iterations required, false otherwise.
34313403 */
3432- static void
3404+ static bool
34333405AbortCurrentTransactionInternal (void )
34343406{
34353407 TransactionState s = CurrentTransactionState ;
34363408
3437- /* This states are handled in AbortCurrentTransaction() */
3438- Assert (s -> blockState != TBLOCK_SUBBEGIN &&
3439- s -> blockState != TBLOCK_SUBRELEASE &&
3440- s -> blockState != TBLOCK_SUBCOMMIT &&
3441- s -> blockState != TBLOCK_SUBABORT_PENDING &&
3442- s -> blockState != TBLOCK_SUBRESTART &&
3443- s -> blockState != TBLOCK_SUBABORT_END &&
3444- s -> blockState != TBLOCK_SUBABORT_RESTART );
3445-
34463409 switch (s -> blockState )
34473410 {
34483411 case TBLOCK_DEFAULT :
@@ -3563,10 +3526,34 @@ AbortCurrentTransactionInternal(void)
35633526 AbortSubTransaction ();
35643527 s -> blockState = TBLOCK_SUBABORT ;
35653528 break ;
3566- default :
3567- /* Keep compiler quiet */
3568- break ;
3529+
3530+ /*
3531+ * If we failed while trying to create a subtransaction, clean up
3532+ * the broken subtransaction and abort the parent. The same
3533+ * applies if we get a failure while ending a subtransaction. As
3534+ * we need to abort the parent, return false to request the caller
3535+ * to do the next iteration.
3536+ */
3537+ case TBLOCK_SUBBEGIN :
3538+ case TBLOCK_SUBRELEASE :
3539+ case TBLOCK_SUBCOMMIT :
3540+ case TBLOCK_SUBABORT_PENDING :
3541+ case TBLOCK_SUBRESTART :
3542+ AbortSubTransaction ();
3543+ CleanupSubTransaction ();
3544+ return false;
3545+
3546+ /*
3547+ * Same as above, except the Abort() was already done.
3548+ */
3549+ case TBLOCK_SUBABORT_END :
3550+ case TBLOCK_SUBABORT_RESTART :
3551+ CleanupSubTransaction ();
3552+ return false;
35693553 }
3554+
3555+ /* Done, no more iterations required */
3556+ return true;
35703557}
35713558
35723559/*
0 commit comments