8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.169 2004/07/01 00:49:42 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.170 2004/07/01 20:11:02 tgl Exp $
12
12
*
13
13
* NOTES
14
14
* Transaction aborts can now occur two ways:
@@ -196,6 +196,7 @@ static void StartSubTransaction(void);
196
196
static void CommitSubTransaction (void );
197
197
static void AbortSubTransaction (void );
198
198
static void CleanupSubTransaction (void );
199
+ static void StartAbortedSubTransaction (void );
199
200
static void PushTransaction (void );
200
201
static void PopTransaction (void );
201
202
@@ -317,7 +318,7 @@ IsAbortedTransactionBlockState(void)
317
318
TransactionState s = CurrentTransactionState ;
318
319
319
320
if (s -> blockState == TBLOCK_ABORT ||
320
- s -> blockState == TBLOCK_SUBABORT )
321
+ s -> blockState == TBLOCK_SUBABORT )
321
322
return true;
322
323
323
324
return false;
@@ -1579,10 +1580,9 @@ StartTransactionCommand(void)
1579
1580
break ;
1580
1581
1581
1582
/*
1582
- * This is the case when are somewhere in a transaction block
1583
+ * This is the case when we are somewhere in a transaction block
1583
1584
* and about to start a new command. For now we do nothing
1584
- * but someday we may do command-local resource
1585
- * initialization.
1585
+ * but someday we may do command-local resource initialization.
1586
1586
*/
1587
1587
case TBLOCK_INPROGRESS :
1588
1588
case TBLOCK_SUBINPROGRESS :
@@ -1699,7 +1699,9 @@ CommitTransactionCommand(void)
1699
1699
1700
1700
/*
1701
1701
* We were just issued a BEGIN inside a transaction block.
1702
- * Start a subtransaction.
1702
+ * Start a subtransaction. (BeginTransactionBlock already
1703
+ * did PushTransaction, so as to have someplace to put the
1704
+ * SUBBEGIN state.)
1703
1705
*/
1704
1706
case TBLOCK_SUBBEGIN :
1705
1707
StartSubTransaction ();
@@ -1711,8 +1713,7 @@ CommitTransactionCommand(void)
1711
1713
* Start a subtransaction, and put it in aborted state.
1712
1714
*/
1713
1715
case TBLOCK_SUBBEGINABORT :
1714
- StartSubTransaction ();
1715
- AbortSubTransaction ();
1716
+ StartAbortedSubTransaction ();
1716
1717
s -> blockState = TBLOCK_SUBABORT ;
1717
1718
break ;
1718
1719
@@ -1724,7 +1725,7 @@ CommitTransactionCommand(void)
1724
1725
break ;
1725
1726
1726
1727
/*
1727
- * We where issued a COMMIT command, so we end the current
1728
+ * We were issued a COMMIT command, so we end the current
1728
1729
* subtransaction and return to the parent transaction.
1729
1730
*/
1730
1731
case TBLOCK_SUBEND :
@@ -1740,7 +1741,7 @@ CommitTransactionCommand(void)
1740
1741
break ;
1741
1742
1742
1743
/*
1743
- * We are ending a subtransaction that aborted nicely ,
1744
+ * We are ending an aborted subtransaction via ROLLBACK ,
1744
1745
* so the parent can be allowed to live.
1745
1746
*/
1746
1747
case TBLOCK_SUBENDABORT_OK :
@@ -1750,9 +1751,8 @@ CommitTransactionCommand(void)
1750
1751
break ;
1751
1752
1752
1753
/*
1753
- * We are ending a subtransaction that aborted in a unclean
1754
- * way (e.g. the user issued COMMIT in an aborted subtrasaction.)
1755
- * Abort the subtransaction, and abort the parent too.
1754
+ * We are ending an aborted subtransaction via COMMIT.
1755
+ * End the subtransaction, and abort the parent too.
1756
1756
*/
1757
1757
case TBLOCK_SUBENDABORT_ERROR :
1758
1758
CleanupSubTransaction ();
@@ -1791,7 +1791,7 @@ AbortCurrentTransaction(void)
1791
1791
break ;
1792
1792
1793
1793
/*
1794
- * If we are in the TBLOCK_BEGIN it means something screwed up
1794
+ * If we are in TBLOCK_BEGIN it means something screwed up
1795
1795
* right after reading "BEGIN TRANSACTION" so we enter the
1796
1796
* abort state. Eventually an "END TRANSACTION" will fix
1797
1797
* things.
@@ -1803,10 +1803,10 @@ AbortCurrentTransaction(void)
1803
1803
break ;
1804
1804
1805
1805
/*
1806
- * This is the case when are somewhere in a transaction block
1807
- * which aborted so we abort the transaction and set the ABORT
1808
- * state. Eventually an "END TRANSACTION" will fix things and
1809
- * restore us to a normal state .
1806
+ * This is the case when we are somewhere in a transaction block
1807
+ * and we've gotten a failure, so we abort the transaction and
1808
+ * set up the persistent ABORT state. We will stay in ABORT
1809
+ * until we get an "END TRANSACTION" .
1810
1810
*/
1811
1811
case TBLOCK_INPROGRESS :
1812
1812
AbortTransaction ();
@@ -1817,7 +1817,7 @@ AbortCurrentTransaction(void)
1817
1817
/*
1818
1818
* Here, the system was fouled up just after the user wanted
1819
1819
* to end the transaction block so we abort the transaction
1820
- * and put us back into the default state.
1820
+ * and return to the default state.
1821
1821
*/
1822
1822
case TBLOCK_END :
1823
1823
AbortTransaction ();
@@ -1852,10 +1852,7 @@ AbortCurrentTransaction(void)
1852
1852
*/
1853
1853
case TBLOCK_SUBBEGIN :
1854
1854
case TBLOCK_SUBBEGINABORT :
1855
- PushTransaction ();
1856
- s = CurrentTransactionState ; /* changed by push */
1857
- StartSubTransaction ();
1858
- AbortSubTransaction ();
1855
+ StartAbortedSubTransaction ();
1859
1856
s -> blockState = TBLOCK_SUBABORT ;
1860
1857
break ;
1861
1858
@@ -2092,8 +2089,10 @@ CallEOXactCallbacks(bool isCommit)
2092
2089
* transaction block support
2093
2090
* ----------------------------------------------------------------
2094
2091
*/
2092
+
2095
2093
/*
2096
2094
* BeginTransactionBlock
2095
+ * This executes a BEGIN command.
2097
2096
*/
2098
2097
void
2099
2098
BeginTransactionBlock (void )
@@ -2102,7 +2101,7 @@ BeginTransactionBlock(void)
2102
2101
2103
2102
switch (s -> blockState ) {
2104
2103
/*
2105
- * We are inside a transaction, so allow a transaction block
2104
+ * We are not inside a transaction block , so allow one
2106
2105
* to begin.
2107
2106
*/
2108
2107
case TBLOCK_STARTED :
@@ -2149,6 +2148,7 @@ BeginTransactionBlock(void)
2149
2148
2150
2149
/*
2151
2150
* EndTransactionBlock
2151
+ * This executes a COMMIT command.
2152
2152
*/
2153
2153
void
2154
2154
EndTransactionBlock (void )
@@ -2176,9 +2176,9 @@ EndTransactionBlock(void)
2176
2176
break ;
2177
2177
2178
2178
/*
2179
- * here, we are in a transaction block which aborted and since the
2180
- * AbortTransaction() was already done, we do whatever is needed
2181
- * and change to the special "END ABORT" state. The upcoming
2179
+ * here, we are in a transaction block which aborted. Since the
2180
+ * AbortTransaction() was already done, we need only
2181
+ * change to the special "END ABORT" state. The upcoming
2182
2182
* CommitTransactionCommand() will recognise this and then put us
2183
2183
* back in the default state.
2184
2184
*/
@@ -2189,7 +2189,8 @@ EndTransactionBlock(void)
2189
2189
/*
2190
2190
* here we are in an aborted subtransaction. Signal
2191
2191
* CommitTransactionCommand() to clean up and return to the
2192
- * parent transaction.
2192
+ * parent transaction. Since the user said COMMIT, we must
2193
+ * fail the parent transaction.
2193
2194
*/
2194
2195
case TBLOCK_SUBABORT :
2195
2196
s -> blockState = TBLOCK_SUBENDABORT_ERROR ;
@@ -2209,7 +2210,7 @@ EndTransactionBlock(void)
2209
2210
s -> blockState = TBLOCK_ENDABORT ;
2210
2211
break ;
2211
2212
2212
- /* These cases are invalid. Reject them altogether . */
2213
+ /* these cases are invalid. */
2213
2214
case TBLOCK_DEFAULT :
2214
2215
case TBLOCK_BEGIN :
2215
2216
case TBLOCK_ENDABORT :
@@ -2227,6 +2228,7 @@ EndTransactionBlock(void)
2227
2228
2228
2229
/*
2229
2230
* UserAbortTransactionBlock
2231
+ * This executes a ROLLBACK command.
2230
2232
*/
2231
2233
void
2232
2234
UserAbortTransactionBlock (void )
@@ -2244,7 +2246,10 @@ UserAbortTransactionBlock(void)
2244
2246
s -> blockState = TBLOCK_ENDABORT ;
2245
2247
break ;
2246
2248
2247
- /* Ditto, for a subtransaction. */
2249
+ /*
2250
+ * Ditto, for a subtransaction. Here it is okay to allow the
2251
+ * parent transaction to continue.
2252
+ */
2248
2253
case TBLOCK_SUBABORT :
2249
2254
s -> blockState = TBLOCK_SUBENDABORT_OK ;
2250
2255
break ;
@@ -2336,8 +2341,8 @@ AbortOutOfAnyTransaction(void)
2336
2341
case TBLOCK_SUBBEGIN :
2337
2342
case TBLOCK_SUBBEGINABORT :
2338
2343
/*
2339
- * Just starting a new transaction -- return to parent.
2340
- * FIXME -- Is this correct?
2344
+ * We didn't get as far as starting the subxact, so there's
2345
+ * nothing to abort. Just pop back to parent.
2341
2346
*/
2342
2347
PopTransaction ();
2343
2348
s = CurrentTransactionState ; /* changed by pop */
@@ -2353,6 +2358,7 @@ AbortOutOfAnyTransaction(void)
2353
2358
case TBLOCK_SUBABORT :
2354
2359
case TBLOCK_SUBENDABORT_OK :
2355
2360
case TBLOCK_SUBENDABORT_ERROR :
2361
+ /* As above, but AbortSubTransaction already done */
2356
2362
CleanupSubTransaction ();
2357
2363
PopTransaction ();
2358
2364
s = CurrentTransactionState ; /* changed by pop */
@@ -2521,6 +2527,8 @@ CommitSubTransaction(void)
2521
2527
AtSubCommit_Portals (s -> parent -> transactionIdData );
2522
2528
DeferredTriggerEndSubXact (true);
2523
2529
2530
+ s -> state = TRANS_COMMIT ;
2531
+
2524
2532
/* Mark subtransaction as subcommitted */
2525
2533
CommandCounterIncrement ();
2526
2534
RecordSubTransactionCommit ();
@@ -2642,6 +2650,49 @@ CleanupSubTransaction(void)
2642
2650
s -> state = TRANS_DEFAULT ;
2643
2651
}
2644
2652
2653
+ /*
2654
+ * StartAbortedSubTransaction
2655
+ *
2656
+ * This function is used to start a subtransaction and put it immediately
2657
+ * into aborted state. The end result should be equivalent to
2658
+ * StartSubTransaction immediately followed by AbortSubTransaction.
2659
+ * The reason we don't implement it just that way is that many of the backend
2660
+ * modules aren't designed to handle starting a subtransaction when not
2661
+ * inside a valid transaction. Rather than making them all capable of
2662
+ * doing that, we just omit the paired start and abort calls in this path.
2663
+ */
2664
+ static void
2665
+ StartAbortedSubTransaction (void )
2666
+ {
2667
+ TransactionState s = CurrentTransactionState ;
2668
+
2669
+ if (s -> state != TRANS_DEFAULT )
2670
+ elog (WARNING , "StartAbortedSubTransaction and not in default state" );
2671
+
2672
+ s -> state = TRANS_START ;
2673
+
2674
+ /*
2675
+ * We don't bother to generate a new Xid, so the end state is not
2676
+ * *exactly* like we had done a full Start/AbortSubTransaction...
2677
+ */
2678
+ s -> transactionIdData = InvalidTransactionId ;
2679
+
2680
+ /* Make sure currentUser is reasonably valid */
2681
+ Assert (s -> parent != NULL );
2682
+ s -> currentUser = s -> parent -> currentUser ;
2683
+
2684
+ /*
2685
+ * Initialize only what has to be there for CleanupSubTransaction to work.
2686
+ */
2687
+ AtSubStart_Memory ();
2688
+
2689
+ s -> state = TRANS_ABORT ;
2690
+
2691
+ AtSubAbort_Memory ();
2692
+
2693
+ ShowTransactionState ("StartAbortedSubTransaction" );
2694
+ }
2695
+
2645
2696
/*
2646
2697
* PushTransaction
2647
2698
* Set up transaction state for a subtransaction
@@ -2672,6 +2723,7 @@ PushTransaction(void)
2672
2723
*/
2673
2724
s -> transactionIdData = p -> transactionIdData ;
2674
2725
s -> curTransactionContext = p -> curTransactionContext ;
2726
+ s -> currentUser = p -> currentUser ;
2675
2727
2676
2728
CurrentTransactionState = s ;
2677
2729
}
0 commit comments