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
224224ResourceOwner curTransactionOwner ;/* my query resources */
225225List * childXids ;/* subcommitted child XIDs */
226226AclId currentUser ;/* subxact start current_user */
227+ bool prevXactReadOnly ;/* entry-time xact r/o state */
227228struct TransactionStateData * parent ;/* back link to parent */
228229}TransactionStateData ;
229230
@@ -284,6 +285,7 @@ static TransactionStateData TopTransactionStateData = {
284285NULL ,/* cur transaction resource owner */
285286NIL ,/* subcommitted child Xids */
2862870 ,/* entry-time current userid */
288+ false,/* entry-time xact r/o state */
287289NULL /* link to parent state block */
288290};
289291
@@ -1242,7 +1244,8 @@ StartTransaction(void)
12421244 * check the current transaction state
12431245 */
12441246if (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 */
13211326if (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 ));
13231329Assert (s -> parent == NULL );
13241330
13251331/*
@@ -1351,14 +1357,14 @@ CommitTransaction(void)
13511357
13521358AtCommit_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 */
13591364AtCommit_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 */
13621368AtEOXact_UpdatePasswordFile (true);
13631369
13641370/*
@@ -1486,7 +1492,8 @@ AbortTransaction(void)
14861492 * check the current transaction state
14871493 */
14881494if (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 ));
14901497Assert (s -> parent == NULL );
14911498
14921499/*
@@ -1515,7 +1522,7 @@ AbortTransaction(void)
15151522 */
15161523DeferredTriggerAbortXact ();
15171524AtAbort_Portals ();
1518- lo_commit (false);/* 'false' means it's abort */
1525+ AtEOXact_LargeObject (false);/* 'false' means it's abort */
15191526AtAbort_Notify ();
15201527AtEOXact_UpdatePasswordFile (false);
15211528
@@ -1870,6 +1877,9 @@ CleanupAbortedSubTransactions(bool returnName)
18701877s = CurrentTransactionState ;
18711878}
18721879
1880+ AssertState (s -> blockState == TBLOCK_SUBINPROGRESS ||
1881+ s -> blockState == TBLOCK_INPROGRESS );
1882+
18731883return name ;
18741884}
18751885
@@ -2866,7 +2876,8 @@ StartSubTransaction(void)
28662876TransactionState s = CurrentTransactionState ;
28672877
28682878if (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
28712882s -> state = TRANS_START ;
28722883
@@ -2889,6 +2900,7 @@ StartSubTransaction(void)
28892900 * Finish setup of other transaction state fields.
28902901 */
28912902s -> currentUser = GetUserId ();
2903+ s -> prevXactReadOnly = XactReadOnly ;
28922904
28932905/*
28942906 * Initialize other subsystems for new subtransaction
@@ -2913,7 +2925,8 @@ CommitSubTransaction(void)
29132925ShowTransactionState ("CommitSubTransaction" );
29142926
29152927if (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 */
29192932AtSubCommit_Portals (s -> parent -> transactionIdData ,
@@ -2930,9 +2943,18 @@ CommitSubTransaction(void)
29302943/* Post-commit cleanup */
29312944AtSubCommit_smgr ();
29322945
2933- AtSubEOXact_Inval (true);
2946+ AtEOSubXact_Inval (true);
29342947AtEOSubXact_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)
29532975AtEOSubXact_on_commit_actions (true,s -> transactionIdData ,
29542976s -> 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+
29562985CurrentResourceOwner = s -> parent -> curTransactionOwner ;
29572986CurTransactionResourceOwner = s -> parent -> curTransactionOwner ;
29582987s -> curTransactionOwner = NULL ;
@@ -2973,7 +3002,8 @@ AbortSubTransaction(void)
29733002ShowTransactionState ("AbortSubTransaction" );
29743003
29753004if (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
29783008HOLD_INTERRUPTS ();
29793009
@@ -3010,7 +3040,16 @@ AbortSubTransaction(void)
30103040AtEOSubXact_SPI (false,s -> transactionIdData );
30113041AtSubAbort_Portals (s -> parent -> transactionIdData ,
30123042s -> 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
30153054ResourceOwnerRelease (s -> curTransactionOwner ,
30163055RESOURCE_RELEASE_BEFORE_LOCKS ,
@@ -3041,6 +3080,13 @@ AbortSubTransaction(void)
30413080 */
30423081SetUserId (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+
30443090CommandCounterIncrement ();
30453091
30463092RESUME_INTERRUPTS ();
@@ -3057,7 +3103,8 @@ CleanupSubTransaction(void)
30573103ShowTransactionState ("CleanupSubTransaction" );
30583104
30593105if (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
30623109AtSubCleanup_Portals ();
30633110
@@ -3088,7 +3135,8 @@ StartAbortedSubTransaction(void)
30883135TransactionState s = CurrentTransactionState ;
30893136
30903137if (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
30933141s -> state = TRANS_START ;
30943142
@@ -3168,7 +3216,8 @@ PopTransaction(void)
31683216TransactionState s = CurrentTransactionState ;
31693217
31703218if (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
31733222if (s -> parent == NULL )
31743223elog (FATAL ,"PopTransaction with no parent" );