88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.172 2004/07/27 05:10:49 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.173 2004/07/28 14:23:27 tgl Exp $
1212 *
1313 * NOTES
1414 * Transaction aborts can now occur two ways:
@@ -224,6 +224,7 @@ typedef struct TransactionStateData
224224 ResourceOwner curTransactionOwner ; /* my query resources */
225225 List * childXids ; /* subcommitted child XIDs */
226226 AclId currentUser ; /* subxact start current_user */
227+ bool prevXactReadOnly ; /* entry-time xact r/o state */
227228 struct TransactionStateData * parent ; /* back link to parent */
228229} TransactionStateData ;
229230
@@ -284,6 +285,7 @@ static TransactionStateData TopTransactionStateData = {
284285 NULL , /* cur transaction resource owner */
285286 NIL , /* subcommitted child Xids */
286287 0 , /* entry-time current userid */
288+ false, /* entry-time xact r/o state */
287289 NULL /* link to parent state block */
288290};
289291
@@ -1242,7 +1244,8 @@ StartTransaction(void)
12421244 * check the current transaction state
12431245 */
12441246 if (s -> state != TRANS_DEFAULT )
1245- elog (WARNING , "StartTransaction and not in default state" );
1247+ elog (WARNING , "StartTransaction while in %s state" ,
1248+ TransStateAsString (s -> state ));
12461249
12471250 /*
12481251 * set the current transaction state information appropriately during
@@ -1287,6 +1290,8 @@ StartTransaction(void)
12871290 * you won't because it doesn't work during startup; the userid isn't
12881291 * set yet during a backend's first transaction start. We only use
12891292 * the currentUser field in sub-transaction state structs.
1293+ *
1294+ * prevXactReadOnly is also valid only in sub-transactions.
12901295 */
12911296
12921297 /*
@@ -1319,7 +1324,8 @@ CommitTransaction(void)
13191324 * check the current transaction state
13201325 */
13211326 if (s -> state != TRANS_INPROGRESS )
1322- elog (WARNING , "CommitTransaction and not in in-progress state" );
1327+ elog (WARNING , "CommitTransaction while in %s state" ,
1328+ TransStateAsString (s -> state ));
13231329 Assert (s -> parent == NULL );
13241330
13251331 /*
@@ -1351,14 +1357,14 @@ CommitTransaction(void)
13511357
13521358 AtCommit_Portals ();
13531359
1354- /* handle commit for large objects [ PA, 7/17/98 ] */
1355- /* XXX probably this does not belong here */
1356- lo_commit (true);
1360+ /* close large objects before lower-level cleanup */
1361+ AtEOXact_LargeObject (true);
13571362
13581363 /* NOTIFY commit must come before lower-level cleanup */
13591364 AtCommit_Notify ();
13601365
13611366 /* Update the flat password file if we changed pg_shadow or pg_group */
1367+ /* This should be the last step before commit */
13621368 AtEOXact_UpdatePasswordFile (true);
13631369
13641370 /*
@@ -1486,7 +1492,8 @@ AbortTransaction(void)
14861492 * check the current transaction state
14871493 */
14881494 if (s -> state != TRANS_INPROGRESS )
1489- elog (WARNING , "AbortTransaction and not in in-progress state" );
1495+ elog (WARNING , "AbortTransaction while in %s state" ,
1496+ TransStateAsString (s -> state ));
14901497 Assert (s -> parent == NULL );
14911498
14921499 /*
@@ -1515,7 +1522,7 @@ AbortTransaction(void)
15151522 */
15161523 DeferredTriggerAbortXact ();
15171524 AtAbort_Portals ();
1518- lo_commit (false); /* 'false' means it's abort */
1525+ AtEOXact_LargeObject (false); /* 'false' means it's abort */
15191526 AtAbort_Notify ();
15201527 AtEOXact_UpdatePasswordFile (false);
15211528
@@ -1870,6 +1877,9 @@ CleanupAbortedSubTransactions(bool returnName)
18701877 s = CurrentTransactionState ;
18711878 }
18721879
1880+ AssertState (s -> blockState == TBLOCK_SUBINPROGRESS ||
1881+ s -> blockState == TBLOCK_INPROGRESS );
1882+
18731883 return name ;
18741884}
18751885
@@ -2866,7 +2876,8 @@ StartSubTransaction(void)
28662876 TransactionState s = CurrentTransactionState ;
28672877
28682878 if (s -> state != TRANS_DEFAULT )
2869- elog (WARNING , "StartSubTransaction and not in default state" );
2879+ elog (WARNING , "StartSubTransaction while in %s state" ,
2880+ TransStateAsString (s -> state ));
28702881
28712882 s -> state = TRANS_START ;
28722883
@@ -2889,6 +2900,7 @@ StartSubTransaction(void)
28892900 * Finish setup of other transaction state fields.
28902901 */
28912902 s -> currentUser = GetUserId ();
2903+ s -> prevXactReadOnly = XactReadOnly ;
28922904
28932905 /*
28942906 * Initialize other subsystems for new subtransaction
@@ -2913,7 +2925,8 @@ CommitSubTransaction(void)
29132925 ShowTransactionState ("CommitSubTransaction" );
29142926
29152927 if (s -> state != TRANS_INPROGRESS )
2916- elog (WARNING , "CommitSubTransaction and not in in-progress state" );
2928+ elog (WARNING , "CommitSubTransaction while in %s state" ,
2929+ TransStateAsString (s -> state ));
29172930
29182931 /* Pre-commit processing */
29192932 AtSubCommit_Portals (s -> parent -> transactionIdData ,
@@ -2930,9 +2943,18 @@ CommitSubTransaction(void)
29302943 /* Post-commit cleanup */
29312944 AtSubCommit_smgr ();
29322945
2933- AtSubEOXact_Inval (true);
2946+ AtEOSubXact_Inval (true);
29342947 AtEOSubXact_SPI (true, s -> transactionIdData );
29352948
2949+ AtEOSubXact_LargeObject (true, s -> transactionIdData ,
2950+ s -> parent -> transactionIdData );
2951+ AtEOSubXact_UpdatePasswordFile (true, s -> transactionIdData ,
2952+ s -> parent -> transactionIdData );
2953+ AtEOSubXact_Files (true, s -> transactionIdData ,
2954+ s -> parent -> transactionIdData );
2955+ AtEOSubXact_Namespace (true, s -> transactionIdData ,
2956+ s -> parent -> transactionIdData );
2957+
29362958 /*
29372959 * Note that we just release the resource owner's resources and don't
29382960 * delete it. This is because locks are not actually released here.
@@ -2953,6 +2975,13 @@ CommitSubTransaction(void)
29532975 AtEOSubXact_on_commit_actions (true, s -> transactionIdData ,
29542976 s -> parent -> transactionIdData );
29552977
2978+ /*
2979+ * We need to restore the upper transaction's read-only state,
2980+ * in case the upper is read-write while the child is read-only;
2981+ * GUC will incorrectly think it should leave the child state in place.
2982+ */
2983+ XactReadOnly = s -> prevXactReadOnly ;
2984+
29562985 CurrentResourceOwner = s -> parent -> curTransactionOwner ;
29572986 CurTransactionResourceOwner = s -> parent -> curTransactionOwner ;
29582987 s -> curTransactionOwner = NULL ;
@@ -2973,7 +3002,8 @@ AbortSubTransaction(void)
29733002 ShowTransactionState ("AbortSubTransaction" );
29743003
29753004 if (s -> state != TRANS_INPROGRESS )
2976- elog (WARNING , "AbortSubTransaction and not in in-progress state" );
3005+ elog (WARNING , "AbortSubTransaction while in %s state" ,
3006+ TransStateAsString (s -> state ));
29773007
29783008 HOLD_INTERRUPTS ();
29793009
@@ -3010,7 +3040,16 @@ AbortSubTransaction(void)
30103040 AtEOSubXact_SPI (false, s -> transactionIdData );
30113041 AtSubAbort_Portals (s -> parent -> transactionIdData ,
30123042 s -> parent -> curTransactionOwner );
3013- AtSubEOXact_Inval (false);
3043+ AtEOSubXact_Inval (false);
3044+
3045+ AtEOSubXact_LargeObject (false, s -> transactionIdData ,
3046+ s -> parent -> transactionIdData );
3047+ AtEOSubXact_UpdatePasswordFile (false, s -> transactionIdData ,
3048+ s -> parent -> transactionIdData );
3049+ AtEOSubXact_Files (false, s -> transactionIdData ,
3050+ s -> parent -> transactionIdData );
3051+ AtEOSubXact_Namespace (false, s -> transactionIdData ,
3052+ s -> parent -> transactionIdData );
30143053
30153054 ResourceOwnerRelease (s -> curTransactionOwner ,
30163055 RESOURCE_RELEASE_BEFORE_LOCKS ,
@@ -3041,6 +3080,13 @@ AbortSubTransaction(void)
30413080 */
30423081 SetUserId (s -> currentUser );
30433082
3083+ /*
3084+ * Restore the upper transaction's read-only state, too. This should
3085+ * be redundant with GUC's cleanup but we may as well do it for
3086+ * consistency with the commit case.
3087+ */
3088+ XactReadOnly = s -> prevXactReadOnly ;
3089+
30443090 CommandCounterIncrement ();
30453091
30463092 RESUME_INTERRUPTS ();
@@ -3057,7 +3103,8 @@ CleanupSubTransaction(void)
30573103 ShowTransactionState ("CleanupSubTransaction" );
30583104
30593105 if (s -> state != TRANS_ABORT )
3060- elog (WARNING , "CleanupSubTransaction and not in aborted state" );
3106+ elog (WARNING , "CleanupSubTransaction while in %s state" ,
3107+ TransStateAsString (s -> state ));
30613108
30623109 AtSubCleanup_Portals ();
30633110
@@ -3088,7 +3135,8 @@ StartAbortedSubTransaction(void)
30883135 TransactionState s = CurrentTransactionState ;
30893136
30903137 if (s -> state != TRANS_DEFAULT )
3091- elog (WARNING , "StartAbortedSubTransaction and not in default state" );
3138+ elog (WARNING , "StartAbortedSubTransaction while in %s state" ,
3139+ TransStateAsString (s -> state ));
30923140
30933141 s -> state = TRANS_START ;
30943142
@@ -3168,7 +3216,8 @@ PopTransaction(void)
31683216 TransactionState s = CurrentTransactionState ;
31693217
31703218 if (s -> state != TRANS_DEFAULT )
3171- elog (WARNING , "PopTransaction and not in default state" );
3219+ elog (WARNING , "PopTransaction while in %s state" ,
3220+ TransStateAsString (s -> state ));
31723221
31733222 if (s -> parent == NULL )
31743223 elog (FATAL , "PopTransaction with no parent" );
0 commit comments