8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
* NOTES
14
14
* Transaction aborts can now occur two ways:
@@ -224,6 +224,7 @@ typedef struct TransactionStateData
224
224
ResourceOwner curTransactionOwner ; /* my query resources */
225
225
List * childXids ; /* subcommitted child XIDs */
226
226
AclId currentUser ; /* subxact start current_user */
227
+ bool prevXactReadOnly ; /* entry-time xact r/o state */
227
228
struct TransactionStateData * parent ; /* back link to parent */
228
229
} TransactionStateData ;
229
230
@@ -284,6 +285,7 @@ static TransactionStateData TopTransactionStateData = {
284
285
NULL , /* cur transaction resource owner */
285
286
NIL , /* subcommitted child Xids */
286
287
0 , /* entry-time current userid */
288
+ false, /* entry-time xact r/o state */
287
289
NULL /* link to parent state block */
288
290
};
289
291
@@ -1242,7 +1244,8 @@ StartTransaction(void)
1242
1244
* check the current transaction state
1243
1245
*/
1244
1246
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 ));
1246
1249
1247
1250
/*
1248
1251
* set the current transaction state information appropriately during
@@ -1287,6 +1290,8 @@ StartTransaction(void)
1287
1290
* you won't because it doesn't work during startup; the userid isn't
1288
1291
* set yet during a backend's first transaction start. We only use
1289
1292
* the currentUser field in sub-transaction state structs.
1293
+ *
1294
+ * prevXactReadOnly is also valid only in sub-transactions.
1290
1295
*/
1291
1296
1292
1297
/*
@@ -1319,7 +1324,8 @@ CommitTransaction(void)
1319
1324
* check the current transaction state
1320
1325
*/
1321
1326
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 ));
1323
1329
Assert (s -> parent == NULL );
1324
1330
1325
1331
/*
@@ -1351,14 +1357,14 @@ CommitTransaction(void)
1351
1357
1352
1358
AtCommit_Portals ();
1353
1359
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);
1357
1362
1358
1363
/* NOTIFY commit must come before lower-level cleanup */
1359
1364
AtCommit_Notify ();
1360
1365
1361
1366
/* Update the flat password file if we changed pg_shadow or pg_group */
1367
+ /* This should be the last step before commit */
1362
1368
AtEOXact_UpdatePasswordFile (true);
1363
1369
1364
1370
/*
@@ -1486,7 +1492,8 @@ AbortTransaction(void)
1486
1492
* check the current transaction state
1487
1493
*/
1488
1494
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 ));
1490
1497
Assert (s -> parent == NULL );
1491
1498
1492
1499
/*
@@ -1515,7 +1522,7 @@ AbortTransaction(void)
1515
1522
*/
1516
1523
DeferredTriggerAbortXact ();
1517
1524
AtAbort_Portals ();
1518
- lo_commit (false); /* 'false' means it's abort */
1525
+ AtEOXact_LargeObject (false); /* 'false' means it's abort */
1519
1526
AtAbort_Notify ();
1520
1527
AtEOXact_UpdatePasswordFile (false);
1521
1528
@@ -1870,6 +1877,9 @@ CleanupAbortedSubTransactions(bool returnName)
1870
1877
s = CurrentTransactionState ;
1871
1878
}
1872
1879
1880
+ AssertState (s -> blockState == TBLOCK_SUBINPROGRESS ||
1881
+ s -> blockState == TBLOCK_INPROGRESS );
1882
+
1873
1883
return name ;
1874
1884
}
1875
1885
@@ -2866,7 +2876,8 @@ StartSubTransaction(void)
2866
2876
TransactionState s = CurrentTransactionState ;
2867
2877
2868
2878
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 ));
2870
2881
2871
2882
s -> state = TRANS_START ;
2872
2883
@@ -2889,6 +2900,7 @@ StartSubTransaction(void)
2889
2900
* Finish setup of other transaction state fields.
2890
2901
*/
2891
2902
s -> currentUser = GetUserId ();
2903
+ s -> prevXactReadOnly = XactReadOnly ;
2892
2904
2893
2905
/*
2894
2906
* Initialize other subsystems for new subtransaction
@@ -2913,7 +2925,8 @@ CommitSubTransaction(void)
2913
2925
ShowTransactionState ("CommitSubTransaction" );
2914
2926
2915
2927
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 ));
2917
2930
2918
2931
/* Pre-commit processing */
2919
2932
AtSubCommit_Portals (s -> parent -> transactionIdData ,
@@ -2930,9 +2943,18 @@ CommitSubTransaction(void)
2930
2943
/* Post-commit cleanup */
2931
2944
AtSubCommit_smgr ();
2932
2945
2933
- AtSubEOXact_Inval (true);
2946
+ AtEOSubXact_Inval (true);
2934
2947
AtEOSubXact_SPI (true, s -> transactionIdData );
2935
2948
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
+
2936
2958
/*
2937
2959
* Note that we just release the resource owner's resources and don't
2938
2960
* delete it. This is because locks are not actually released here.
@@ -2953,6 +2975,13 @@ CommitSubTransaction(void)
2953
2975
AtEOSubXact_on_commit_actions (true, s -> transactionIdData ,
2954
2976
s -> parent -> transactionIdData );
2955
2977
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
+
2956
2985
CurrentResourceOwner = s -> parent -> curTransactionOwner ;
2957
2986
CurTransactionResourceOwner = s -> parent -> curTransactionOwner ;
2958
2987
s -> curTransactionOwner = NULL ;
@@ -2973,7 +3002,8 @@ AbortSubTransaction(void)
2973
3002
ShowTransactionState ("AbortSubTransaction" );
2974
3003
2975
3004
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 ));
2977
3007
2978
3008
HOLD_INTERRUPTS ();
2979
3009
@@ -3010,7 +3040,16 @@ AbortSubTransaction(void)
3010
3040
AtEOSubXact_SPI (false, s -> transactionIdData );
3011
3041
AtSubAbort_Portals (s -> parent -> transactionIdData ,
3012
3042
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 );
3014
3053
3015
3054
ResourceOwnerRelease (s -> curTransactionOwner ,
3016
3055
RESOURCE_RELEASE_BEFORE_LOCKS ,
@@ -3041,6 +3080,13 @@ AbortSubTransaction(void)
3041
3080
*/
3042
3081
SetUserId (s -> currentUser );
3043
3082
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
+
3044
3090
CommandCounterIncrement ();
3045
3091
3046
3092
RESUME_INTERRUPTS ();
@@ -3057,7 +3103,8 @@ CleanupSubTransaction(void)
3057
3103
ShowTransactionState ("CleanupSubTransaction" );
3058
3104
3059
3105
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 ));
3061
3108
3062
3109
AtSubCleanup_Portals ();
3063
3110
@@ -3088,7 +3135,8 @@ StartAbortedSubTransaction(void)
3088
3135
TransactionState s = CurrentTransactionState ;
3089
3136
3090
3137
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 ));
3092
3140
3093
3141
s -> state = TRANS_START ;
3094
3142
@@ -3168,7 +3216,8 @@ PopTransaction(void)
3168
3216
TransactionState s = CurrentTransactionState ;
3169
3217
3170
3218
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 ));
3172
3221
3173
3222
if (s -> parent == NULL )
3174
3223
elog (FATAL , "PopTransaction with no parent" );
0 commit comments