@@ -269,7 +269,7 @@ static TransactionId RecordTransactionAbort(bool isSubXact);
269269static void StartTransaction (void );
270270
271271static void StartSubTransaction (void );
272- static void CommitSubTransaction (bool isTopLevel );
272+ static void CommitSubTransaction (void );
273273static void AbortSubTransaction (void );
274274static void CleanupSubTransaction (void );
275275static void PushTransaction (void );
@@ -2578,7 +2578,7 @@ CommitTransactionCommand(void)
25782578case TBLOCK_SUBRELEASE :
25792579do
25802580{
2581- CommitSubTransaction (false );
2581+ CommitSubTransaction ();
25822582s = CurrentTransactionState ;/* changed by pop */
25832583}while (s -> blockState == TBLOCK_SUBRELEASE );
25842584
@@ -2588,12 +2588,17 @@ CommitTransactionCommand(void)
25882588
25892589/*
25902590 * We were issued a COMMIT, so we end the current subtransaction
2591- * hierarchy and perform final commit.
2591+ * hierarchy and perform final commit. We do this by rolling up
2592+ * any subtransactions into their parent, which leads to O(N^2)
2593+ * operations with respect to resource owners - this isn't that
2594+ * bad until we approach a thousands of savepoints but is necessary
2595+ * for correctness should after triggers create new resource
2596+ * owners.
25922597 */
25932598case TBLOCK_SUBCOMMIT :
25942599do
25952600{
2596- CommitSubTransaction (true );
2601+ CommitSubTransaction ();
25972602s = CurrentTransactionState ;/* changed by pop */
25982603}while (s -> blockState == TBLOCK_SUBCOMMIT );
25992604/* If we had a COMMIT command, finish off the main xact too */
@@ -3745,7 +3750,7 @@ ReleaseCurrentSubTransaction(void)
37453750BlockStateAsString (s -> blockState ));
37463751Assert (s -> state == TRANS_INPROGRESS );
37473752MemoryContextSwitchTo (CurTransactionContext );
3748- CommitSubTransaction (false );
3753+ CommitSubTransaction ();
37493754s = CurrentTransactionState ;/* changed by pop */
37503755Assert (s -> state == TRANS_INPROGRESS );
37513756}
@@ -4009,13 +4014,9 @@ StartSubTransaction(void)
40094014 *
40104015 *The caller has to make sure to always reassign CurrentTransactionState
40114016 *if it has a local pointer to it after calling this function.
4012- *
4013- *isTopLevel means that this CommitSubTransaction() is being issued as a
4014- *sequence of actions leading directly to a main transaction commit
4015- *allowing some actions to be optimised.
40164017 */
40174018static void
4018- CommitSubTransaction (bool isTopLevel )
4019+ CommitSubTransaction (void )
40194020{
40204021TransactionState s = CurrentTransactionState ;
40214022
@@ -4069,14 +4070,10 @@ CommitSubTransaction(bool isTopLevel)
40694070
40704071/*
40714072 * Other locks should get transferred to their parent resource owner.
4072- * Doing that is an O(N^2) operation, so if isTopLevel then we can just
4073- * leave the lock records as they are, knowing they will all get released
4074- * by the top level commit using ProcReleaseLocks(). We only optimize
4075- * this for commit; aborts may need to do other cleanup.
40764073 */
40774074ResourceOwnerRelease (s -> curTransactionOwner ,
40784075RESOURCE_RELEASE_LOCKS ,
4079- true,isTopLevel );
4076+ true,false );
40804077ResourceOwnerRelease (s -> curTransactionOwner ,
40814078RESOURCE_RELEASE_AFTER_LOCKS ,
40824079 true, false);