Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * xact.c
4 : * top level transaction system support routines
5 : *
6 : * See src/backend/access/transam/README for more information.
7 : *
8 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
9 : * Portions Copyright (c) 1994, Regents of the University of California
10 : *
11 : *
12 : * IDENTIFICATION
13 : * src/backend/access/transam/xact.c
14 : *
15 : *-------------------------------------------------------------------------
16 : */
17 :
18 : #include "postgres.h"
19 :
20 : #include <time.h>
21 : #include <unistd.h>
22 :
23 : #include "access/commit_ts.h"
24 : #include "access/multixact.h"
25 : #include "access/parallel.h"
26 : #include "access/subtrans.h"
27 : #include "access/transam.h"
28 : #include "access/twophase.h"
29 : #include "access/xact.h"
30 : #include "access/xlog.h"
31 : #include "access/xloginsert.h"
32 : #include "access/xlogrecovery.h"
33 : #include "access/xlogutils.h"
34 : #include "catalog/index.h"
35 : #include "catalog/namespace.h"
36 : #include "catalog/pg_enum.h"
37 : #include "catalog/storage.h"
38 : #include "commands/async.h"
39 : #include "commands/tablecmds.h"
40 : #include "commands/trigger.h"
41 : #include "common/pg_prng.h"
42 : #include "executor/spi.h"
43 : #include "libpq/be-fsstubs.h"
44 : #include "libpq/pqsignal.h"
45 : #include "miscadmin.h"
46 : #include "pg_trace.h"
47 : #include "pgstat.h"
48 : #include "replication/logical.h"
49 : #include "replication/logicallauncher.h"
50 : #include "replication/logicalworker.h"
51 : #include "replication/origin.h"
52 : #include "replication/snapbuild.h"
53 : #include "replication/syncrep.h"
54 : #include "replication/walsender.h"
55 : #include "storage/condition_variable.h"
56 : #include "storage/fd.h"
57 : #include "storage/lmgr.h"
58 : #include "storage/md.h"
59 : #include "storage/predicate.h"
60 : #include "storage/proc.h"
61 : #include "storage/procarray.h"
62 : #include "storage/sinvaladt.h"
63 : #include "storage/smgr.h"
64 : #include "utils/builtins.h"
65 : #include "utils/catcache.h"
66 : #include "utils/combocid.h"
67 : #include "utils/guc.h"
68 : #include "utils/inval.h"
69 : #include "utils/memutils.h"
70 : #include "utils/relmapper.h"
71 : #include "utils/snapmgr.h"
72 : #include "utils/timeout.h"
73 : #include "utils/timestamp.h"
74 :
75 : /*
76 : * User-tweakable parameters
77 : */
78 : int DefaultXactIsoLevel = XACT_READ_COMMITTED;
79 : int XactIsoLevel = XACT_READ_COMMITTED;
80 :
81 : bool DefaultXactReadOnly = false;
82 : bool XactReadOnly;
83 :
84 : bool DefaultXactDeferrable = false;
85 : bool XactDeferrable;
86 :
87 : int synchronous_commit = SYNCHRONOUS_COMMIT_ON;
88 :
89 : /*
90 : * CheckXidAlive is a xid value pointing to a possibly ongoing (sub)
91 : * transaction. Currently, it is used in logical decoding. It's possible
92 : * that such transactions can get aborted while the decoding is ongoing in
93 : * which case we skip decoding that particular transaction. To ensure that we
94 : * check whether the CheckXidAlive is aborted after fetching the tuple from
95 : * system tables. We also ensure that during logical decoding we never
96 : * directly access the tableam or heap APIs because we are checking for the
97 : * concurrent aborts only in systable_* APIs.
98 : */
99 : TransactionId CheckXidAlive = InvalidTransactionId;
100 : bool bsysscan = false;
101 :
102 : /*
103 : * When running as a parallel worker, we place only a single
104 : * TransactionStateData on the parallel worker's state stack, and the XID
105 : * reflected there will be that of the *innermost* currently-active
106 : * subtransaction in the backend that initiated parallelism. However,
107 : * GetTopTransactionId() and TransactionIdIsCurrentTransactionId()
108 : * need to return the same answers in the parallel worker as they would have
109 : * in the user backend, so we need some additional bookkeeping.
110 : *
111 : * XactTopFullTransactionId stores the XID of our toplevel transaction, which
112 : * will be the same as TopTransactionStateData.fullTransactionId in an
113 : * ordinary backend; but in a parallel backend, which does not have the entire
114 : * transaction state, it will instead be copied from the backend that started
115 : * the parallel operation.
116 : *
117 : * nParallelCurrentXids will be 0 and ParallelCurrentXids NULL in an ordinary
118 : * backend, but in a parallel backend, nParallelCurrentXids will contain the
119 : * number of XIDs that need to be considered current, and ParallelCurrentXids
120 : * will contain the XIDs themselves. This includes all XIDs that were current
121 : * or sub-committed in the parent at the time the parallel operation began.
122 : * The XIDs are stored sorted in numerical order (not logical order) to make
123 : * lookups as fast as possible.
124 : */
125 : static FullTransactionId XactTopFullTransactionId = {InvalidTransactionId};
126 : static int nParallelCurrentXids = 0;
127 : static TransactionId *ParallelCurrentXids;
128 :
129 : /*
130 : * Miscellaneous flag bits to record events which occur on the top level
131 : * transaction. These flags are only persisted in MyXactFlags and are intended
132 : * so we remember to do certain things later on in the transaction. This is
133 : * globally accessible, so can be set from anywhere in the code that requires
134 : * recording flags.
135 : */
136 : int MyXactFlags;
137 :
138 : /*
139 : * transaction states - transaction state from server perspective
140 : */
141 : typedef enum TransState
142 : {
143 : TRANS_DEFAULT, /* idle */
144 : TRANS_START, /* transaction starting */
145 : TRANS_INPROGRESS, /* inside a valid transaction */
146 : TRANS_COMMIT, /* commit in progress */
147 : TRANS_ABORT, /* abort in progress */
148 : TRANS_PREPARE /* prepare in progress */
149 : } TransState;
150 :
151 : /*
152 : * transaction block states - transaction state of client queries
153 : *
154 : * Note: the subtransaction states are used only for non-topmost
155 : * transactions; the others appear only in the topmost transaction.
156 : */
157 : typedef enum TBlockState
158 : {
159 : /* not-in-transaction-block states */
160 : TBLOCK_DEFAULT, /* idle */
161 : TBLOCK_STARTED, /* running single-query transaction */
162 :
163 : /* transaction block states */
164 : TBLOCK_BEGIN, /* starting transaction block */
165 : TBLOCK_INPROGRESS, /* live transaction */
166 : TBLOCK_IMPLICIT_INPROGRESS, /* live transaction after implicit BEGIN */
167 : TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */
168 : TBLOCK_END, /* COMMIT received */
169 : TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
170 : TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
171 : TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
172 : TBLOCK_PREPARE, /* live xact, PREPARE received */
173 :
174 : /* subtransaction states */
175 : TBLOCK_SUBBEGIN, /* starting a subtransaction */
176 : TBLOCK_SUBINPROGRESS, /* live subtransaction */
177 : TBLOCK_SUBRELEASE, /* RELEASE received */
178 : TBLOCK_SUBCOMMIT, /* COMMIT received while TBLOCK_SUBINPROGRESS */
179 : TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
180 : TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
181 : TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
182 : TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
183 : TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
184 : } TBlockState;
185 :
186 : /*
187 : * transaction state structure
188 : */
189 : typedef struct TransactionStateData
190 : {
191 : FullTransactionId fullTransactionId; /* my FullTransactionId */
192 : SubTransactionId subTransactionId; /* my subxact ID */
193 : char *name; /* savepoint name, if any */
194 : int savepointLevel; /* savepoint level */
195 : TransState state; /* low-level state */
196 : TBlockState blockState; /* high-level state */
197 : int nestingLevel; /* transaction nesting depth */
198 : int gucNestLevel; /* GUC context nesting depth */
199 : MemoryContext curTransactionContext; /* my xact-lifetime context */
200 : ResourceOwner curTransactionOwner; /* my query resources */
201 : TransactionId *childXids; /* subcommitted child XIDs, in XID order */
202 : int nChildXids; /* # of subcommitted child XIDs */
203 : int maxChildXids; /* allocated size of childXids[] */
204 : Oid prevUser; /* previous CurrentUserId setting */
205 : int prevSecContext; /* previous SecurityRestrictionContext */
206 : bool prevXactReadOnly; /* entry-time xact r/o state */
207 : bool startedInRecovery; /* did we start in recovery? */
208 : bool didLogXid; /* has xid been included in WAL record? */
209 : int parallelModeLevel; /* Enter/ExitParallelMode counter */
210 : bool chain; /* start a new block after this one */
211 : bool topXidLogged; /* for a subxact: is top-level XID logged? */
212 : struct TransactionStateData *parent; /* back link to parent */
213 : } TransactionStateData;
214 :
215 : typedef TransactionStateData *TransactionState;
216 :
217 : /*
218 : * Serialized representation used to transmit transaction state to parallel
219 : * workers through shared memory.
220 : */
221 : typedef struct SerializedTransactionState
222 : {
223 : int xactIsoLevel;
224 : bool xactDeferrable;
225 : FullTransactionId topFullTransactionId;
226 : FullTransactionId currentFullTransactionId;
227 : CommandId currentCommandId;
228 : int nParallelCurrentXids;
229 : TransactionId parallelCurrentXids[FLEXIBLE_ARRAY_MEMBER];
230 : } SerializedTransactionState;
231 :
232 : /* The size of SerializedTransactionState, not including the final array. */
233 : #define SerializedTransactionStateHeaderSize \
234 : offsetof(SerializedTransactionState, parallelCurrentXids)
235 :
236 : /*
237 : * CurrentTransactionState always points to the current transaction state
238 : * block. It will point to TopTransactionStateData when not in a
239 : * transaction at all, or when in a top-level transaction.
240 : */
241 : static TransactionStateData TopTransactionStateData = {
242 : .state = TRANS_DEFAULT,
243 : .blockState = TBLOCK_DEFAULT,
244 : .topXidLogged = false,
245 : };
246 :
247 : /*
248 : * unreportedXids holds XIDs of all subtransactions that have not yet been
249 : * reported in an XLOG_XACT_ASSIGNMENT record.
250 : */
251 : static int nUnreportedXids;
252 : static TransactionId unreportedXids[PGPROC_MAX_CACHED_SUBXIDS];
253 :
254 : static TransactionState CurrentTransactionState = &TopTransactionStateData;
255 :
256 : /*
257 : * The subtransaction ID and command ID assignment counters are global
258 : * to a whole transaction, so we do not keep them in the state stack.
259 : */
260 : static SubTransactionId currentSubTransactionId;
261 : static CommandId currentCommandId;
262 : static bool currentCommandIdUsed;
263 :
264 : /*
265 : * xactStartTimestamp is the value of transaction_timestamp().
266 : * stmtStartTimestamp is the value of statement_timestamp().
267 : * xactStopTimestamp is the time at which we log a commit / abort WAL record,
268 : * or if that was skipped, the time of the first subsequent
269 : * GetCurrentTransactionStopTimestamp() call.
270 : *
271 : * These do not change as we enter and exit subtransactions, so we don't
272 : * keep them inside the TransactionState stack.
273 : */
274 : static TimestampTz xactStartTimestamp;
275 : static TimestampTz stmtStartTimestamp;
276 : static TimestampTz xactStopTimestamp;
277 :
278 : /*
279 : * GID to be used for preparing the current transaction. This is also
280 : * global to a whole transaction, so we don't keep it in the state stack.
281 : */
282 : static char *prepareGID;
283 :
284 : /*
285 : * Some commands want to force synchronous commit.
286 : */
287 : static bool forceSyncCommit = false;
288 :
289 : /* Flag for logging statements in a transaction. */
290 : bool xact_is_sampled = false;
291 :
292 : /*
293 : * Private context for transaction-abort work --- we reserve space for this
294 : * at startup to ensure that AbortTransaction and AbortSubTransaction can work
295 : * when we've run out of memory.
296 : */
297 : static MemoryContext TransactionAbortContext = NULL;
298 :
299 : /*
300 : * List of add-on start- and end-of-xact callbacks
301 : */
302 : typedef struct XactCallbackItem
303 : {
304 : struct XactCallbackItem *next;
305 : XactCallback callback;
306 : void *arg;
307 : } XactCallbackItem;
308 :
309 : static XactCallbackItem *Xact_callbacks = NULL;
310 :
311 : /*
312 : * List of add-on start- and end-of-subxact callbacks
313 : */
314 : typedef struct SubXactCallbackItem
315 : {
316 : struct SubXactCallbackItem *next;
317 : SubXactCallback callback;
318 : void *arg;
319 : } SubXactCallbackItem;
320 :
321 : static SubXactCallbackItem *SubXact_callbacks = NULL;
322 :
323 :
324 : /* local function prototypes */
325 : static void AssignTransactionId(TransactionState s);
326 : static void AbortTransaction(void);
327 : static void AtAbort_Memory(void);
328 : static void AtCleanup_Memory(void);
329 : static void AtAbort_ResourceOwner(void);
330 : static void AtCCI_LocalCache(void);
331 : static void AtCommit_Memory(void);
332 : static void AtStart_Cache(void);
333 : static void AtStart_Memory(void);
334 : static void AtStart_ResourceOwner(void);
335 : static void CallXactCallbacks(XactEvent event);
336 : static void CallSubXactCallbacks(SubXactEvent event,
337 : SubTransactionId mySubid,
338 : SubTransactionId parentSubid);
339 : static void CleanupTransaction(void);
340 : static void CheckTransactionBlock(bool isTopLevel, bool throwError,
341 : const char *stmtType);
342 : static void CommitTransaction(void);
343 : static TransactionId RecordTransactionAbort(bool isSubXact);
344 : static void StartTransaction(void);
345 :
346 : static void StartSubTransaction(void);
347 : static void CommitSubTransaction(void);
348 : static void AbortSubTransaction(void);
349 : static void CleanupSubTransaction(void);
350 : static void PushTransaction(void);
351 : static void PopTransaction(void);
352 :
353 : static void AtSubAbort_Memory(void);
354 : static void AtSubCleanup_Memory(void);
355 : static void AtSubAbort_ResourceOwner(void);
356 : static void AtSubCommit_Memory(void);
357 : static void AtSubStart_Memory(void);
358 : static void AtSubStart_ResourceOwner(void);
359 :
360 : static void ShowTransactionState(const char *str);
361 : static void ShowTransactionStateRec(const char *str, TransactionState s);
362 : static const char *BlockStateAsString(TBlockState blockState);
363 : static const char *TransStateAsString(TransState state);
364 :
365 :
366 : /* ----------------------------------------------------------------
367 : * transaction state accessors
368 : * ----------------------------------------------------------------
369 : */
370 :
371 : /*
372 : * IsTransactionState
373 : *
374 : * This returns true if we are inside a valid transaction; that is,
375 : * it is safe to initiate database access, take heavyweight locks, etc.
376 : */
377 : bool
9646 bruce 378 GIC 84355117 : IsTransactionState(void)
379 : {
9345 380 84355117 : TransactionState s = CurrentTransactionState;
381 :
9345 bruce 382 ECB : /*
383 : * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However, we
5624 384 : * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
385 : * TRANS_PREPARE since it might be too soon or too late within those
386 : * transition states to do anything interesting. Hence, the only "valid"
387 : * state is TRANS_INPROGRESS.
388 : */
5785 tgl 389 GIC 84355117 : return (s->state == TRANS_INPROGRESS);
390 : }
391 :
392 : /*
7452 bruce 393 ECB : * IsAbortedTransactionBlockState
394 : *
395 : * This returns true if we are within an aborted transaction block.
396 : */
397 : bool
8202 tgl 398 GIC 984167 : IsAbortedTransactionBlockState(void)
399 : {
9345 bruce 400 984167 : TransactionState s = CurrentTransactionState;
401 :
6797 bruce 402 CBC 984167 : if (s->blockState == TBLOCK_ABORT ||
6856 tgl 403 GIC 982840 : s->blockState == TBLOCK_SUBABORT)
9345 bruce 404 CBC 1609 : return true;
405 :
406 982558 : return false;
9770 scrappy 407 ECB : }
408 :
409 :
6856 tgl 410 : /*
411 : * GetTopTransactionId
412 : *
413 : * This will return the XID of the main transaction, assigning one if
414 : * it's not yet set. Be careful to call this only inside a valid xact.
415 : */
416 : TransactionId
6856 tgl 417 GIC 28513 : GetTopTransactionId(void)
418 : {
1473 tmunro 419 28513 : if (!FullTransactionIdIsValid(XactTopFullTransactionId))
5695 tgl 420 442 : AssignTransactionId(&TopTransactionStateData);
1473 tmunro 421 CBC 28513 : return XidFromFullTransactionId(XactTopFullTransactionId);
422 : }
6856 tgl 423 ECB :
5695 424 : /*
425 : * GetTopTransactionIdIfAny
426 : *
427 : * This will return the XID of the main transaction, if one is assigned.
428 : * It will return InvalidTransactionId if we are not currently inside a
429 : * transaction, or inside a transaction that hasn't yet been assigned an XID.
430 : */
431 : TransactionId
5695 tgl 432 GIC 59035627 : GetTopTransactionIdIfAny(void)
433 : {
1473 tmunro 434 59035627 : return XidFromFullTransactionId(XactTopFullTransactionId);
435 : }
6856 tgl 436 ECB :
437 : /*
7452 bruce 438 : * GetCurrentTransactionId
439 : *
440 : * This will return the XID of the current transaction (main or sub
441 : * transaction), assigning one if it's not yet set. Be careful to call this
442 : * only inside a valid xact.
443 : */
444 : TransactionId
8202 tgl 445 GIC 14968177 : GetCurrentTransactionId(void)
446 : {
9345 bruce 447 14968177 : TransactionState s = CurrentTransactionState;
448 :
1473 tmunro 449 CBC 14968177 : if (!FullTransactionIdIsValid(s->fullTransactionId))
5695 tgl 450 GIC 297768 : AssignTransactionId(s);
1473 tmunro 451 CBC 14968177 : return XidFromFullTransactionId(s->fullTransactionId);
452 : }
6779 tgl 453 ECB :
5695 454 : /*
455 : * GetCurrentTransactionIdIfAny
456 : *
457 : * This will return the XID of the current sub xact, if one is assigned.
458 : * It will return InvalidTransactionId if we are not currently inside a
459 : * transaction, or inside a transaction that hasn't been assigned an XID yet.
460 : */
461 : TransactionId
5695 tgl 462 GIC 19431086 : GetCurrentTransactionIdIfAny(void)
463 : {
1473 tmunro 464 19431086 : return XidFromFullTransactionId(CurrentTransactionState->fullTransactionId);
465 : }
1473 tmunro 466 ECB :
467 : /*
468 : * GetTopFullTransactionId
469 : *
470 : * This will return the FullTransactionId of the main transaction, assigning
471 : * one if it's not yet set. Be careful to call this only inside a valid xact.
472 : */
473 : FullTransactionId
1473 tmunro 474 GIC 2865 : GetTopFullTransactionId(void)
475 : {
476 2865 : if (!FullTransactionIdIsValid(XactTopFullTransactionId))
477 2068 : AssignTransactionId(&TopTransactionStateData);
1473 tmunro 478 CBC 2865 : return XactTopFullTransactionId;
479 : }
1473 tmunro 480 ECB :
481 : /*
482 : * GetTopFullTransactionIdIfAny
483 : *
484 : * This will return the FullTransactionId of the main transaction, if one is
485 : * assigned. It will return InvalidFullTransactionId if we are not currently
486 : * inside a transaction, or inside a transaction that hasn't yet been assigned
487 : * one.
488 : */
489 : FullTransactionId
1473 tmunro 490 GIC 12 : GetTopFullTransactionIdIfAny(void)
491 : {
492 12 : return XactTopFullTransactionId;
493 : }
1473 tmunro 494 ECB :
495 : /*
496 : * GetCurrentFullTransactionId
497 : *
498 : * This will return the FullTransactionId of the current transaction (main or
499 : * sub transaction), assigning one if it's not yet set. Be careful to call
500 : * this only inside a valid xact.
501 : */
502 : FullTransactionId
1473 tmunro 503 UIC 0 : GetCurrentFullTransactionId(void)
504 : {
505 0 : TransactionState s = CurrentTransactionState;
506 :
1473 tmunro 507 UBC 0 : if (!FullTransactionIdIsValid(s->fullTransactionId))
1473 tmunro 508 UIC 0 : AssignTransactionId(s);
1473 tmunro 509 UBC 0 : return s->fullTransactionId;
510 : }
1473 tmunro 511 EUB :
512 : /*
513 : * GetCurrentFullTransactionIdIfAny
514 : *
515 : * This will return the FullTransactionId of the current sub xact, if one is
516 : * assigned. It will return InvalidFullTransactionId if we are not currently
517 : * inside a transaction, or inside a transaction that hasn't been assigned one
518 : * yet.
519 : */
520 : FullTransactionId
1473 tmunro 521 UIC 0 : GetCurrentFullTransactionIdIfAny(void)
522 : {
523 0 : return CurrentTransactionState->fullTransactionId;
524 : }
5695 tgl 525 EUB :
526 : /*
3407 rhaas 527 : * MarkCurrentTransactionIdLoggedIfAny
528 : *
529 : * Remember that the current xid - if it is assigned - now has been wal logged.
530 : */
531 : void
3407 rhaas 532 GIC 19399402 : MarkCurrentTransactionIdLoggedIfAny(void)
533 : {
1473 tmunro 534 19399402 : if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId))
3407 rhaas 535 18866959 : CurrentTransactionState->didLogXid = true;
3407 rhaas 536 CBC 19399402 : }
537 :
523 akapila 538 ECB : /*
539 : * IsSubxactTopXidLogPending
540 : *
541 : * This is used to decide whether we need to WAL log the top-level XID for
542 : * operation in a subtransaction. We require that for logical decoding, see
543 : * LogicalDecodingProcessRecord.
544 : *
545 : * This returns true if wal_level >= logical and we are inside a valid
546 : * subtransaction, for which the assignment was not yet written to any WAL
547 : * record.
548 : */
549 : bool
523 akapila 550 GIC 19404628 : IsSubxactTopXidLogPending(void)
551 : {
552 : /* check whether it is already logged */
553 19404628 : if (CurrentTransactionState->topXidLogged)
523 akapila 554 CBC 102108 : return false;
555 :
556 : /* wal_level has to be logical */
557 19302520 : if (!XLogLogicalInfoActive())
558 18494195 : return false;
559 :
560 : /* we need to be in a transaction state */
561 808325 : if (!IsTransactionState())
562 4156 : return false;
563 :
564 : /* it has to be a subtransaction */
565 804169 : if (!IsSubTransaction())
566 803693 : return false;
567 :
568 : /* the subtransaction has to have a XID assigned */
569 476 : if (!TransactionIdIsValid(GetCurrentTransactionIdIfAny()))
570 6 : return false;
571 :
523 akapila 572 GIC 470 : return true;
523 akapila 573 ECB : }
574 :
575 : /*
576 : * MarkSubxactTopXidLogged
577 : *
578 : * Remember that the top transaction id for the current subtransaction is WAL
579 : * logged now.
580 : */
581 : void
523 akapila 582 GIC 234 : MarkSubxactTopXidLogged(void)
583 : {
584 234 : Assert(IsSubxactTopXidLogPending());
585 :
523 akapila 586 CBC 234 : CurrentTransactionState->topXidLogged = true;
523 akapila 587 GIC 234 : }
3407 rhaas 588 ECB :
589 : /*
3984 simon 590 : * GetStableLatestTransactionId
3985 591 : *
592 : * Get the transaction's XID if it has one, else read the next-to-be-assigned
593 : * XID. Once we have a value, return that same value for the remainder of the
594 : * current transaction. This is meant to provide the reference point for the
595 : * age(xid) function, but might be useful for other maintenance tasks as well.
596 : */
597 : TransactionId
3985 simon 598 GIC 113 : GetStableLatestTransactionId(void)
599 : {
600 : static LocalTransactionId lxid = InvalidLocalTransactionId;
601 : static TransactionId stablexid = InvalidTransactionId;
3985 simon 602 ECB :
3984 simon 603 GIC 113 : if (lxid != MyProc->lxid)
604 : {
3985 605 1 : lxid = MyProc->lxid;
3984 606 1 : stablexid = GetTopTransactionIdIfAny();
3984 simon 607 CBC 1 : if (!TransactionIdIsValid(stablexid))
783 tmunro 608 GIC 1 : stablexid = ReadNextTransactionId();
3985 simon 609 ECB : }
610 :
3984 simon 611 CBC 113 : Assert(TransactionIdIsValid(stablexid));
3984 simon 612 ECB :
3985 simon 613 GIC 113 : return stablexid;
614 : }
3985 simon 615 ECB :
616 : /*
5695 tgl 617 : * AssignTransactionId
618 : *
619 : * Assigns a new permanent FullTransactionId to the given TransactionState.
620 : * We do not assign XIDs to transactions until/unless this is called.
621 : * Also, any parent TransactionStates that don't yet have XIDs are assigned
622 : * one; this maintains the invariant that a child transaction has an XID
623 : * following its parent's.
624 : */
625 : static void
5695 tgl 626 GIC 301436 : AssignTransactionId(TransactionState s)
627 : {
5624 bruce 628 301436 : bool isSubXact = (s->parent != NULL);
629 : ResourceOwner currentOwner;
3260 bruce 630 CBC 301436 : bool log_unknown_top = false;
631 :
5695 tgl 632 ECB : /* Assert that caller didn't screw up */
1473 tmunro 633 GIC 301436 : Assert(!FullTransactionIdIsValid(s->fullTransactionId));
6779 tgl 634 CBC 301436 : Assert(s->state == TRANS_INPROGRESS);
635 :
636 : /*
2878 bruce 637 ECB : * Workers synchronize transaction state at the beginning of each parallel
638 : * operation, so we can't account for new XIDs at this point.
639 : */
2732 rhaas 640 GIC 301436 : if (IsInParallelMode() || IsParallelWorker())
2901 rhaas 641 UIC 0 : elog(ERROR, "cannot assign XIDs during a parallel operation");
642 :
643 : /*
5695 tgl 644 ECB : * Ensure parent(s) have XIDs, so that a child always has an XID later
1418 tgl 645 EUB : * than its parent. Mustn't recurse here, or we might get a stack
646 : * overflow if we're at the bottom of a huge stack of subtransactions none
647 : * of which have XIDs yet.
648 : */
1473 tmunro 649 GIC 301436 : if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId))
650 : {
4382 bruce 651 619 : TransactionState p = s->parent;
652 : TransactionState *parents;
4382 bruce 653 CBC 619 : size_t parentOffset = 0;
654 :
655 619 : parents = palloc(sizeof(TransactionState) * s->nestingLevel);
1473 tmunro 656 GIC 1777 : while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
4643 rhaas 657 ECB : {
4643 rhaas 658 GIC 1158 : parents[parentOffset++] = p;
4643 rhaas 659 CBC 1158 : p = p->parent;
4643 rhaas 660 ECB : }
661 :
662 : /*
4382 bruce 663 : * This is technically a recursive call, but the recursion will never
664 : * be more than one layer deep.
665 : */
4643 rhaas 666 GIC 1777 : while (parentOffset != 0)
667 1158 : AssignTransactionId(parents[--parentOffset]);
668 :
669 619 : pfree(parents);
4643 rhaas 670 ECB : }
6779 tgl 671 :
672 : /*
3407 rhaas 673 : * When wal_level=logical, guarantee that a subtransaction's xid can only
674 : * be seen in the WAL stream if its toplevel xid has been logged before.
675 : * If necessary we log an xact_assignment record with fewer than
676 : * PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't set
677 : * for a transaction even though it appears in a WAL record, we just might
678 : * superfluously log something. That can happen when an xid is included
679 : * somewhere inside a wal record, but not in XLogRecord->xl_xid, like in
680 : * xl_standby_locks.
681 : */
3407 rhaas 682 GIC 301436 : if (isSubXact && XLogLogicalInfoActive() &&
683 317 : !TopTransactionStateData.didLogXid)
684 23 : log_unknown_top = true;
685 :
6779 tgl 686 ECB : /*
687 : * Generate a new FullTransactionId and record its xid in PGPROC and
1473 tmunro 688 : * pg_subtrans.
689 : *
690 : * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
691 : * shared storage other than PGPROC; because if there's no room for it in
692 : * PGPROC, the subtrans entry is needed to ensure that other backends see
693 : * the Xid as "running". See GetNewTransactionId.
694 : */
1473 tmunro 695 GIC 301436 : s->fullTransactionId = GetNewTransactionId(isSubXact);
2901 rhaas 696 301436 : if (!isSubXact)
1473 tmunro 697 298022 : XactTopFullTransactionId = s->fullTransactionId;
698 :
5695 tgl 699 CBC 301436 : if (isSubXact)
1473 tmunro 700 3414 : SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),
701 3414 : XidFromFullTransactionId(s->parent->fullTransactionId));
702 :
4356 tgl 703 ECB : /*
704 : * If it's a top-level transaction, the predicate locking system needs to
705 : * be told about it too.
706 : */
4356 tgl 707 GIC 301436 : if (!isSubXact)
1473 tmunro 708 298022 : RegisterPredicateLockingXid(XidFromFullTransactionId(s->fullTransactionId));
709 :
710 : /*
5624 bruce 711 ECB : * Acquire lock on the transaction XID. (We assume this cannot block.) We
712 : * have to ensure that the lock is assigned to the transaction's own
713 : * ResourceOwner.
714 : */
6779 tgl 715 GIC 301436 : currentOwner = CurrentResourceOwner;
2006 716 301436 : CurrentResourceOwner = s->curTransactionOwner;
717 :
1473 tmunro 718 301436 : XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));
2006 tgl 719 ECB :
6779 tgl 720 CBC 301436 : CurrentResourceOwner = currentOwner;
721 :
4859 simon 722 ECB : /*
723 : * Every PGPROC_MAX_CACHED_SUBXIDS assigned transaction ids within each
724 : * top-level transaction we issue a WAL record for the assignment. We
725 : * include the top-level xid and all the subxids that have not yet been
726 : * reported using XLOG_XACT_ASSIGNMENT records.
727 : *
728 : * This is required to limit the amount of shared memory required in a hot
729 : * standby server to keep track of in-progress XIDs. See notes for
730 : * RecordKnownAssignedTransactionIds().
731 : *
732 : * We don't keep track of the immediate parent of each subxid, only the
733 : * top-level transaction that each subxact belongs to. This is correct in
734 : * recovery only because aborted subtransactions are separately WAL
735 : * logged.
736 : *
737 : * This is correct even for the case where several levels above us didn't
738 : * have an xid assigned as we recursed up to them beforehand.
739 : */
4859 simon 740 GIC 301436 : if (isSubXact && XLogStandbyInfoActive())
741 : {
1473 tmunro 742 2898 : unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);
4859 simon 743 2898 : nUnreportedXids++;
4859 simon 744 ECB :
745 : /*
4790 bruce 746 : * ensure this test matches similar one in
747 : * RecoverPreparedTransactions()
748 : */
3407 rhaas 749 GIC 2898 : if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS ||
750 : log_unknown_top)
751 : {
752 : xl_xact_assignment xlrec;
4859 simon 753 ECB :
754 : /*
755 : * xtop is always set by now because we recurse up transaction
756 : * stack to the highest unassigned xid and then come back down
757 : */
4859 simon 758 GIC 52 : xlrec.xtop = GetTopTransactionId();
759 52 : Assert(TransactionIdIsValid(xlrec.xtop));
760 52 : xlrec.nsubxacts = nUnreportedXids;
761 :
3062 heikki.linnakangas 762 CBC 52 : XLogBeginInsert();
763 52 : XLogRegisterData((char *) &xlrec, MinSizeOfXactAssignment);
764 52 : XLogRegisterData((char *) unreportedXids,
765 : nUnreportedXids * sizeof(TransactionId));
4859 simon 766 ECB :
3062 heikki.linnakangas 767 CBC 52 : (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
4859 simon 768 ECB :
4859 simon 769 GIC 52 : nUnreportedXids = 0;
770 : /* mark top, not current xact as having been logged */
3407 rhaas 771 CBC 52 : TopTransactionStateData.didLogXid = true;
772 : }
4859 simon 773 ECB : }
4859 simon 774 GIC 301436 : }
6779 tgl 775 ECB :
776 : /*
777 : * GetCurrentSubTransactionId
778 : */
779 : SubTransactionId
6779 tgl 780 GIC 2118084 : GetCurrentSubTransactionId(void)
781 : {
782 2118084 : TransactionState s = CurrentTransactionState;
783 :
6779 tgl 784 CBC 2118084 : return s->subTransactionId;
785 : }
9770 scrappy 786 ECB :
787 : /*
3689 tgl 788 : * SubTransactionIsActive
789 : *
790 : * Test if the specified subxact ID is still active. Note caller is
791 : * responsible for checking whether this ID is relevant to the current xact.
792 : */
793 : bool
3689 tgl 794 GIC 28513 : SubTransactionIsActive(SubTransactionId subxid)
795 : {
796 : TransactionState s;
797 :
3689 tgl 798 CBC 28519 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
799 : {
3689 tgl 800 GIC 28519 : if (s->state == TRANS_ABORT)
3689 tgl 801 UIC 0 : continue;
3689 tgl 802 CBC 28519 : if (s->subTransactionId == subxid)
3689 tgl 803 GIC 28513 : return true;
3689 tgl 804 ECB : }
3689 tgl 805 UBC 0 : return false;
3689 tgl 806 ECB : }
807 :
808 :
7331 bruce 809 EUB : /*
810 : * GetCurrentCommandId
811 : *
812 : * "used" must be true if the caller intends to use the command ID to mark
813 : * inserted/updated/deleted tuples. false means the ID is being fetched
814 : * for read-only purposes (ie, as a snapshot validity cutoff). See
815 : * CommandCounterIncrement() for discussion.
816 : */
817 : CommandId
5609 tgl 818 GIC 10677844 : GetCurrentCommandId(bool used)
819 : {
820 : /* this is global to a transaction, not subtransaction-local */
821 10677844 : if (used)
2901 rhaas 822 ECB : {
823 : /*
824 : * Forbid setting currentCommandIdUsed in a parallel worker, because
1029 andres 825 : * we have no provision for communicating this back to the leader. We
826 : * could relax this restriction when currentCommandIdUsed was already
827 : * true at the start of the parallel operation.
828 : */
1935 rhaas 829 GIC 7964924 : Assert(!IsParallelWorker());
5609 tgl 830 7964924 : currentCommandIdUsed = true;
831 : }
6779 832 10677844 : return currentCommandId;
9770 scrappy 833 ECB : }
834 :
835 : /*
1646 tgl 836 : * SetParallelStartTimestamps
837 : *
838 : * In a parallel worker, we should inherit the parent transaction's
839 : * timestamps rather than setting our own. The parallel worker
840 : * infrastructure must call this to provide those values before
841 : * calling StartTransaction() or SetCurrentStatementStartTimestamp().
842 : */
843 : void
1646 tgl 844 GIC 1298 : SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
845 : {
846 1298 : Assert(IsParallelWorker());
847 1298 : xactStartTimestamp = xact_ts;
1646 tgl 848 CBC 1298 : stmtStartTimestamp = stmt_ts;
1646 tgl 849 GIC 1298 : }
1646 tgl 850 ECB :
7331 bruce 851 : /*
6493 tgl 852 : * GetCurrentTransactionStartTimestamp
7863 lockhart 853 : */
854 : TimestampTz
6493 tgl 855 GIC 42330 : GetCurrentTransactionStartTimestamp(void)
856 : {
857 42330 : return xactStartTimestamp;
858 : }
6856 tgl 859 ECB :
860 : /*
6193 bruce 861 : * GetCurrentStatementStartTimestamp
862 : */
863 : TimestampTz
6193 bruce 864 GIC 1435587 : GetCurrentStatementStartTimestamp(void)
865 : {
866 1435587 : return stmtStartTimestamp;
867 : }
6193 bruce 868 ECB :
869 : /*
5823 tgl 870 : * GetCurrentTransactionStopTimestamp
871 : *
872 : * If the transaction stop time hasn't already been set, which can happen if
873 : * we decided we don't need to log an XLOG record, set xactStopTimestamp.
874 : */
875 : TimestampTz
5823 tgl 876 GIC 1424210 : GetCurrentTransactionStopTimestamp(void)
877 : {
177 andres 878 GNC 1424210 : TransactionState s PG_USED_FOR_ASSERTS_ONLY = CurrentTransactionState;
879 :
880 : /* should only be called after commit / abort processing */
881 1424210 : Assert(s->state == TRANS_DEFAULT ||
882 : s->state == TRANS_COMMIT ||
883 : s->state == TRANS_ABORT ||
884 : s->state == TRANS_PREPARE);
885 :
886 1424210 : if (xactStopTimestamp == 0)
887 424026 : xactStopTimestamp = GetCurrentTimestamp();
888 :
889 1424210 : return xactStopTimestamp;
890 : }
5823 tgl 891 ECB :
892 : /*
893 : * SetCurrentStatementStartTimestamp
1646 894 : *
895 : * In a parallel worker, this should already have been provided by a call
896 : * to SetParallelStartTimestamps().
897 : */
898 : void
6193 bruce 899 CBC 637446 : SetCurrentStatementStartTimestamp(void)
6193 bruce 900 ECB : {
1646 tgl 901 GIC 637446 : if (!IsParallelWorker())
1646 tgl 902 CBC 636148 : stmtStartTimestamp = GetCurrentTimestamp();
903 : else
1646 tgl 904 GIC 1298 : Assert(stmtStartTimestamp != 0);
6193 bruce 905 637446 : }
906 :
907 : /*
6856 tgl 908 ECB : * GetCurrentTransactionNestLevel
909 : *
910 : * Note: this will return zero when not inside any transaction, one when
911 : * inside a top-level transaction, etc.
912 : */
913 : int
6856 tgl 914 GIC 24331693 : GetCurrentTransactionNestLevel(void)
915 : {
916 24331693 : TransactionState s = CurrentTransactionState;
917 :
6856 tgl 918 CBC 24331693 : return s->nestingLevel;
919 : }
7863 lockhart 920 ECB :
921 :
7331 bruce 922 : /*
923 : * TransactionIdIsCurrentTransactionId
924 : */
925 : bool
9770 scrappy 926 GIC 62262724 : TransactionIdIsCurrentTransactionId(TransactionId xid)
927 : {
928 : TransactionState s;
929 :
6622 tgl 930 ECB : /*
931 : * We always say that BootstrapTransactionId is "not my transaction ID"
932 : * even when it is (ie, during bootstrap). Along with the fact that
933 : * transam.c always treats BootstrapTransactionId as already committed,
934 : * this causes the heapam_visibility.c routines to see all tuples as
935 : * committed, which is what we need during bootstrap. (Bootstrap mode
936 : * only inserts tuples, it never updates or deletes them, so all tuples
937 : * can be presumed good immediately.)
938 : *
939 : * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
940 : * not my transaction ID, so we can just return "false" immediately for
941 : * any non-normal XID.
942 : */
5999 tgl 943 GIC 62262724 : if (!TransactionIdIsNormal(xid))
9345 bruce 944 3817403 : return false;
945 :
1245 tmunro 946 58445321 : if (TransactionIdEquals(xid, GetTopTransactionIdIfAny()))
1245 tmunro 947 CBC 44041255 : return true;
1245 tmunro 948 ECB :
949 : /*
2878 bruce 950 : * In parallel workers, the XIDs we must consider as current are stored in
951 : * ParallelCurrentXids rather than the transaction-state stack. Note that
952 : * the XIDs in this array are sorted numerically rather than according to
953 : * transactionIdPrecedes order.
954 : */
2901 rhaas 955 GIC 14404066 : if (nParallelCurrentXids > 0)
956 : {
957 : int low,
958 : high;
2901 rhaas 959 ECB :
2901 rhaas 960 GIC 3692512 : low = 0;
961 3692512 : high = nParallelCurrentXids - 1;
962 14595278 : while (low <= high)
963 : {
2901 rhaas 964 ECB : int middle;
965 : TransactionId probe;
966 :
2901 rhaas 967 GIC 14508016 : middle = low + (high - low) / 2;
968 14508016 : probe = ParallelCurrentXids[middle];
969 14508016 : if (probe == xid)
970 3605250 : return true;
2901 rhaas 971 CBC 10902766 : else if (probe < xid)
972 10815504 : low = middle + 1;
2901 rhaas 973 ECB : else
2901 rhaas 974 CBC 87262 : high = middle - 1;
2901 rhaas 975 ECB : }
2901 rhaas 976 CBC 87262 : return false;
977 : }
2901 rhaas 978 ECB :
979 : /*
6385 bruce 980 : * We will return true for the Xid of the current subtransaction, any of
981 : * its subcommitted children, any of its parents, or any of their
982 : * previously subcommitted children. However, a transaction being aborted
983 : * is no longer "current", even though it may still have an entry on the
984 : * state stack.
985 : */
6798 tgl 986 GIC 21395185 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
987 : {
988 : int low,
989 : high;
9770 scrappy 990 ECB :
6798 tgl 991 GIC 10755113 : if (s->state == TRANS_ABORT)
6798 tgl 992 UIC 0 : continue;
1473 tmunro 993 GIC 10755113 : if (!FullTransactionIdIsValid(s->fullTransactionId))
6779 tgl 994 6923042 : continue; /* it can't have any child XIDs either */
1473 tmunro 995 CBC 3832071 : if (TransactionIdEquals(xid, XidFromFullTransactionId(s->fullTransactionId)))
6856 tgl 996 GBC 68472 : return true;
5501 tgl 997 ECB : /* As the childXids array is ordered, we can use binary search */
5501 tgl 998 CBC 3763599 : low = 0;
999 3763599 : high = s->nChildXids - 1;
1000 3764479 : while (low <= high)
1001 : {
5050 bruce 1002 ECB : int middle;
1003 : TransactionId probe;
5501 tgl 1004 :
5501 tgl 1005 GIC 3890 : middle = low + (high - low) / 2;
1006 3890 : probe = s->childXids[middle];
1007 3890 : if (TransactionIdEquals(probe, xid))
6856 1008 3010 : return true;
5501 tgl 1009 CBC 880 : else if (TransactionIdPrecedes(probe, xid))
1010 803 : low = middle + 1;
5501 tgl 1011 ECB : else
5501 tgl 1012 CBC 77 : high = middle - 1;
6856 tgl 1013 ECB : }
1014 : }
1015 :
6856 tgl 1016 CBC 10640072 : return false;
1017 : }
1018 :
1019 : /*
4859 simon 1020 ECB : * TransactionStartedDuringRecovery
1021 : *
1022 : * Returns true if the current transaction started while recovery was still
1023 : * in progress. Recovery might have ended since so RecoveryInProgress() might
1024 : * return false already.
1025 : */
1026 : bool
4859 simon 1027 GIC 8907096 : TransactionStartedDuringRecovery(void)
1028 : {
1029 8907096 : return CurrentTransactionState->startedInRecovery;
1030 : }
9770 scrappy 1031 ECB :
1032 : /*
2901 rhaas 1033 : * EnterParallelMode
1034 : */
1035 : void
2901 rhaas 1036 GIC 2987 : EnterParallelMode(void)
1037 : {
1038 2987 : TransactionState s = CurrentTransactionState;
1039 :
2901 rhaas 1040 CBC 2987 : Assert(s->parallelModeLevel >= 0);
1041 :
1042 2987 : ++s->parallelModeLevel;
2901 rhaas 1043 GIC 2987 : }
2901 rhaas 1044 ECB :
1045 : /*
1046 : * ExitParallelMode
1047 : */
1048 : void
2901 rhaas 1049 GIC 1686 : ExitParallelMode(void)
1050 : {
1051 1686 : TransactionState s = CurrentTransactionState;
1052 :
2901 rhaas 1053 CBC 1686 : Assert(s->parallelModeLevel > 0);
2901 rhaas 1054 GIC 1686 : Assert(s->parallelModeLevel > 1 || !ParallelContextActive());
2901 rhaas 1055 ECB :
2901 rhaas 1056 GIC 1686 : --s->parallelModeLevel;
2901 rhaas 1057 CBC 1686 : }
2901 rhaas 1058 ECB :
1059 : /*
1060 : * IsInParallelMode
1061 : *
1062 : * Are we in a parallel operation, as either the leader or a worker? Check
1063 : * this to prohibit operations that change backend-local state expected to
1064 : * match across all workers. Mere caches usually don't require such a
1065 : * restriction. State modified in a strict push/pop fashion, such as the
1066 : * active snapshot stack, is often fine.
1067 : */
1068 : bool
2901 rhaas 1069 GIC 6169064 : IsInParallelMode(void)
1070 : {
1071 6169064 : return CurrentTransactionState->parallelModeLevel != 0;
1072 : }
2901 rhaas 1073 ECB :
1074 : /*
7452 bruce 1075 : * CommandCounterIncrement
1076 : */
1077 : void
8202 tgl 1078 GIC 1900778 : CommandCounterIncrement(void)
1079 : {
1080 : /*
1081 : * If the current value of the command counter hasn't been "used" to mark
5050 bruce 1082 ECB : * tuples, we need not increment it, since there's no need to distinguish
1083 : * a read-only command from others. This helps postpone command counter
1084 : * overflow, and keeps no-op CommandCounterIncrement operations cheap.
1085 : */
5609 tgl 1086 GIC 1900778 : if (currentCommandIdUsed)
1087 : {
1088 : /*
1089 : * Workers synchronize transaction state at the beginning of each
2901 rhaas 1090 ECB : * parallel operation, so we can't account for new commands after that
1091 : * point.
1092 : */
2732 rhaas 1093 GIC 1206274 : if (IsInParallelMode() || IsParallelWorker())
2901 rhaas 1094 UIC 0 : elog(ERROR, "cannot start commands during a parallel operation");
1095 :
5609 tgl 1096 GIC 1206274 : currentCommandId += 1;
3499 rhaas 1097 CBC 1206274 : if (currentCommandId == InvalidCommandId)
5609 tgl 1098 EUB : {
5609 tgl 1099 UIC 0 : currentCommandId -= 1;
5609 tgl 1100 LBC 0 : ereport(ERROR,
5609 tgl 1101 ECB : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1102 : errmsg("cannot have more than 2^32-2 commands in a transaction")));
5609 tgl 1103 EUB : }
5609 tgl 1104 GBC 1206274 : currentCommandIdUsed = false;
1105 :
1106 : /* Propagate new command ID into static snapshots */
5445 alvherre 1107 GIC 1206274 : SnapshotSetCommandId(currentCommandId);
5050 bruce 1108 ECB :
1109 : /*
1110 : * Make any catalog changes done by the just-completed command visible
1111 : * in the local syscache. We obviously don't need to do this after a
1112 : * read-only command. (But see hacks in inval.c to make real sure we
1113 : * don't think a command that queued inval messages was read-only.)
1114 : */
4809 tgl 1115 GIC 1206274 : AtCCI_LocalCache();
1116 : }
9770 scrappy 1117 1900775 : }
1118 :
5730 tgl 1119 ECB : /*
1120 : * ForceSyncCommit
1121 : *
1122 : * Interface routine to allow commands to force a synchronous commit of the
1123 : * current top-level transaction. Currently, two-phase commit does not
1124 : * persist and restore this variable. So long as all callers use
1125 : * PreventInTransactionBlock(), that omission has no consequences.
1126 : */
1127 : void
5730 tgl 1128 GIC 878 : ForceSyncCommit(void)
1129 : {
1130 878 : forceSyncCommit = true;
1131 878 : }
5730 tgl 1132 ECB :
1133 :
9770 scrappy 1134 : /* ----------------------------------------------------------------
9345 bruce 1135 : * StartTransaction stuff
1136 : * ----------------------------------------------------------------
1137 : */
1138 :
1139 : /*
1140 : * AtStart_Cache
1141 : */
1142 : static void
8202 tgl 1143 GIC 485395 : AtStart_Cache(void)
1144 : {
7964 1145 485395 : AcceptInvalidationMessages();
9770 scrappy 1146 485395 : }
9770 scrappy 1147 ECB :
1148 : /*
7452 bruce 1149 : * AtStart_Memory
9770 scrappy 1150 : */
1151 : static void
8202 tgl 1152 GIC 485395 : AtStart_Memory(void)
1153 : {
6856 1154 485395 : TransactionState s = CurrentTransactionState;
1155 :
5981 tgl 1156 ECB : /*
1157 : * If this is the first time through, create a private context for
1158 : * AbortTransaction to work in. By reserving some space now, we can
1159 : * insulate AbortTransaction from out-of-memory scenarios. Like
1160 : * ErrorContext, we set it up with slow growth rate and a nonzero minimum
1161 : * size, so that space will be reserved immediately.
1162 : */
5981 tgl 1163 GIC 485395 : if (TransactionAbortContext == NULL)
1164 11433 : TransactionAbortContext =
1640 1165 11433 : AllocSetContextCreate(TopMemoryContext,
1166 : "TransactionAbortContext",
1640 tgl 1167 ECB : 32 * 1024,
1168 : 32 * 1024,
1169 : 32 * 1024);
1170 :
1171 : /*
1172 : * We shouldn't have a transaction context already.
1173 : */
8320 tgl 1174 GIC 485395 : Assert(TopTransactionContext == NULL);
1175 :
1176 : /*
1177 : * Create a toplevel context for the transaction.
9345 bruce 1178 ECB : */
8320 tgl 1179 GIC 485395 : TopTransactionContext =
1180 485395 : AllocSetContextCreate(TopMemoryContext,
1181 : "TopTransactionContext",
1182 : ALLOCSET_DEFAULT_SIZES);
9345 bruce 1183 ECB :
6856 tgl 1184 : /*
1185 : * In a top-level transaction, CurTransactionContext is the same as
1186 : * TopTransactionContext.
1187 : */
6856 tgl 1188 GIC 485395 : CurTransactionContext = TopTransactionContext;
1189 485395 : s->curTransactionContext = CurTransactionContext;
1190 :
1191 : /* Make the CurTransactionContext active. */
6856 tgl 1192 CBC 485395 : MemoryContextSwitchTo(CurTransactionContext);
9770 scrappy 1193 485395 : }
1194 :
1195 : /*
6840 tgl 1196 ECB : * AtStart_ResourceOwner
1197 : */
1198 : static void
6840 tgl 1199 GIC 485395 : AtStart_ResourceOwner(void)
1200 : {
1201 485395 : TransactionState s = CurrentTransactionState;
1202 :
6840 tgl 1203 ECB : /*
1204 : * We shouldn't have a transaction resource owner already.
1205 : */
6840 tgl 1206 GIC 485395 : Assert(TopTransactionResourceOwner == NULL);
1207 :
1208 : /*
1209 : * Create a toplevel resource owner for the transaction.
6840 tgl 1210 ECB : */
6840 tgl 1211 GIC 485395 : s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
1212 :
1213 485395 : TopTransactionResourceOwner = s->curTransactionOwner;
1214 485395 : CurTransactionResourceOwner = s->curTransactionOwner;
6840 tgl 1215 CBC 485395 : CurrentResourceOwner = s->curTransactionOwner;
6840 tgl 1216 GIC 485395 : }
6840 tgl 1217 ECB :
6856 1218 : /* ----------------------------------------------------------------
1219 : * StartSubTransaction stuff
1220 : * ----------------------------------------------------------------
1221 : */
1222 :
1223 : /*
1224 : * AtSubStart_Memory
1225 : */
1226 : static void
6856 tgl 1227 GIC 8783 : AtSubStart_Memory(void)
1228 : {
1229 8783 : TransactionState s = CurrentTransactionState;
1230 :
6856 tgl 1231 CBC 8783 : Assert(CurTransactionContext != NULL);
1232 :
6856 tgl 1233 ECB : /*
1234 : * Create a CurTransactionContext, which will be used to hold data that
6385 bruce 1235 : * survives subtransaction commit but disappears on subtransaction abort.
1236 : * We make it a child of the immediate parent's CurTransactionContext.
1237 : */
6856 tgl 1238 GIC 8783 : CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
1239 : "CurTransactionContext",
1240 : ALLOCSET_DEFAULT_SIZES);
1241 8783 : s->curTransactionContext = CurTransactionContext;
6856 tgl 1242 ECB :
1243 : /* Make the CurTransactionContext active. */
6856 tgl 1244 GIC 8783 : MemoryContextSwitchTo(CurTransactionContext);
6856 tgl 1245 CBC 8783 : }
1246 :
1247 : /*
6840 tgl 1248 ECB : * AtSubStart_ResourceOwner
1249 : */
1250 : static void
6840 tgl 1251 GIC 8783 : AtSubStart_ResourceOwner(void)
1252 : {
1253 8783 : TransactionState s = CurrentTransactionState;
1254 :
6840 tgl 1255 CBC 8783 : Assert(s->parent != NULL);
1256 :
6840 tgl 1257 ECB : /*
1258 : * Create a resource owner for the subtransaction. We make it a child of
6385 bruce 1259 : * the immediate parent's resource owner.
1260 : */
6840 tgl 1261 GIC 8783 : s->curTransactionOwner =
1262 8783 : ResourceOwnerCreate(s->parent->curTransactionOwner,
1263 : "SubTransaction");
1264 :
6840 tgl 1265 CBC 8783 : CurTransactionResourceOwner = s->curTransactionOwner;
1266 8783 : CurrentResourceOwner = s->curTransactionOwner;
6840 tgl 1267 GIC 8783 : }
1268 :
9770 scrappy 1269 ECB : /* ----------------------------------------------------------------
9345 bruce 1270 : * CommitTransaction stuff
9770 scrappy 1271 : * ----------------------------------------------------------------
1272 : */
1273 :
1274 : /*
1275 : * RecordTransactionCommit
1276 : *
1277 : * Returns latest XID among xact and its children, or InvalidTransactionId
1278 : * if the xact has no XID. (We compute that here just because it's easier.)
1279 : *
1280 : * If you change this function, see RecordTransactionCommitPrepared also.
1281 : */
1282 : static TransactionId
4808 tgl 1283 GIC 463648 : RecordTransactionCommit(void)
1284 : {
5695 1285 463648 : TransactionId xid = GetTopTransactionIdIfAny();
5624 bruce 1286 463648 : bool markXidCommitted = TransactionIdIsValid(xid);
5692 tgl 1287 CBC 463648 : TransactionId latestXid = InvalidTransactionId;
1288 : int nrels;
1289 : RelFileLocator *rels;
6856 tgl 1290 ECB : int nchildren;
1291 : TransactionId *children;
368 andres 1292 GIC 463648 : int ndroppedstats = 0;
1293 463648 : xl_xact_stats_item *droppedstats = NULL;
4622 rhaas 1294 463648 : int nmsgs = 0;
4859 simon 1295 463648 : SharedInvalidationMessage *invalMessages = NULL;
4622 rhaas 1296 CBC 463648 : bool RelcacheInitFileInval = false;
4493 rhaas 1297 ECB : bool wrote_xlog;
6856 tgl 1298 :
990 akapila 1299 : /*
1300 : * Log pending invalidations for logical decoding of in-progress
1301 : * transactions. Normally for DDLs, we log this at each command end,
1302 : * however, for certain cases where we directly update the system table
1303 : * without a transaction block, the invalidations are not logged till this
1304 : * time.
1305 : */
990 akapila 1306 GIC 463648 : if (XLogLogicalInfoActive())
1307 12504 : LogLogicalInvalidations();
1308 :
1309 : /* Get data needed for commit record */
4622 rhaas 1310 CBC 463648 : nrels = smgrGetPendingDeletes(true, &rels);
6840 tgl 1311 463648 : nchildren = xactGetCommittedChildren(&children);
368 andres 1312 GIC 463648 : ndroppedstats = pgstat_get_transactional_drops(true, &droppedstats);
4622 rhaas 1313 463648 : if (XLogStandbyInfoActive())
4622 rhaas 1314 CBC 396281 : nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
4622 rhaas 1315 ECB : &RelcacheInitFileInval);
3941 heikki.linnakangas 1316 CBC 463648 : wrote_xlog = (XactLastRecEnd != 0);
4790 bruce 1317 ECB :
7897 tgl 1318 : /*
1319 : * If we haven't been assigned an XID yet, we neither can, nor do we want
5624 bruce 1320 : * to write a COMMIT record.
1321 : */
5695 tgl 1322 GIC 463648 : if (!markXidCommitted)
1323 : {
1324 : /*
1325 : * We expect that every RelationDropStorage is followed by a catalog
5624 bruce 1326 ECB : * update, and hence XID assignment, so we shouldn't get here with any
1327 : * pending deletes. Same is true for dropping stats.
1328 : *
1329 : * Use a real test not just an Assert to check this, since it's a bit
1330 : * fragile.
1331 : */
368 andres 1332 GIC 170150 : if (nrels != 0 || ndroppedstats != 0)
5695 tgl 1333 UIC 0 : elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
1334 :
1335 : /* Can't have child XIDs either; AssignTransactionId enforces this */
5695 tgl 1336 CBC 170150 : Assert(nchildren == 0);
5624 bruce 1337 EUB :
1338 : /*
1339 : * Transactions without an assigned xid can contain invalidation
2542 andres 1340 ECB : * messages (e.g. explicit relcache invalidations or catcache
1341 : * invalidations for inplace updates); standbys need to process those.
1342 : * We can't emit a commit record without an xid, and we don't want to
1343 : * force assigning an xid, because that'd be problematic for e.g.
1344 : * vacuum. Hence we emit a bespoke record for the invalidations. We
1345 : * don't want to use that in case a commit record is emitted, so they
1346 : * happen synchronously with commits (besides not wanting to emit more
1347 : * WAL records).
1348 : */
2542 andres 1349 GIC 170150 : if (nmsgs != 0)
1350 : {
1351 43462 : LogStandbyInvalidations(nmsgs, invalMessages,
1352 : RelcacheInitFileInval);
2495 rhaas 1353 CBC 43462 : wrote_xlog = true; /* not strictly necessary */
1354 : }
2542 andres 1355 ECB :
1356 : /*
5695 tgl 1357 : * If we didn't create XLOG entries, we're done here; otherwise we
1358 : * should trigger flushing those entries the same as a commit record
1359 : * would. This will primarily happen for HOT pruning and the like; we
1360 : * want these to be flushed to disk in due time.
1361 : */
4493 rhaas 1362 GIC 170150 : if (!wrote_xlog)
5695 tgl 1363 122495 : goto cleanup;
1364 : }
1365 : else
5695 tgl 1366 ECB : {
2749 alvherre 1367 : bool replorigin;
1368 :
1369 : /*
1370 : * Are we using the replication origins feature? Or, in other words,
1371 : * are we replaying remote actions?
1372 : */
2749 alvherre 1373 GIC 294329 : replorigin = (replorigin_session_origin != InvalidRepOriginId &&
1374 831 : replorigin_session_origin != DoNotReplicateId);
1375 :
1376 : /*
1377 : * Mark ourselves as within our "commit critical section". This
1378 : * forces any concurrent checkpoint to wait until we've updated
1379 : * pg_xact. Without this, it is possible for the checkpoint to set
1380 : * REDO after the XLOG record but fail to flush the pg_xact update to
1381 : * disk, leading to loss of the transaction commit if the system
1382 : * crashes a little later.
1383 : *
1384 : * Note: we could, but don't bother to, set this flag in
1385 : * RecordTransactionAbort. That's because loss of a transaction abort
1386 : * is noncritical; the presumption would be that it aborted, anyway.
1387 : *
1388 : * It's safe to change the delayChkptFlags flag of our own backend
1389 : * without holding the ProcArrayLock, since we're the only one
1390 : * modifying it. This makes checkpoint's determination of which xacts
366 rhaas 1391 ECB : * are delaying the checkpoint a bit fuzzy, but it doesn't matter.
6815 tgl 1392 : */
366 rhaas 1393 CBC 293498 : Assert((MyProc->delayChkptFlags & DELAY_CHKPT_START) == 0);
5695 tgl 1394 GIC 293498 : START_CRIT_SECTION();
366 rhaas 1395 293498 : MyProc->delayChkptFlags |= DELAY_CHKPT_START;
1396 :
1397 : /*
1398 : * Insert the commit XLOG record.
1399 : */
177 andres 1400 GNC 293498 : XactLogCommitRecord(GetCurrentTransactionStopTimestamp(),
1401 : nchildren, children, nrels, rels,
1402 : ndroppedstats, droppedstats,
1403 : nmsgs, invalMessages,
1404 : RelcacheInitFileInval,
1405 : MyXactFlags,
1406 : InvalidTransactionId, NULL /* plain commit */ );
8202 vadim4o 1407 ECB :
2749 alvherre 1408 GIC 293498 : if (replorigin)
2749 alvherre 1409 ECB : /* Move LSNs forward for this replication origin */
2750 alvherre 1410 GIC 831 : replorigin_session_advance(replorigin_session_origin_lsn,
1411 : XactLastRecEnd);
1412 :
1413 : /*
1414 : * Record commit timestamp. The value comes from plain commit
1415 : * timestamp if there's no replication origin; otherwise, the
1416 : * timestamp was already set in replorigin_session_origin_timestamp by
1417 : * replication.
1418 : *
1419 : * We don't need to WAL-log anything here, as the commit record
1420 : * written above already contains the data.
1421 : */
2749 alvherre 1422 ECB :
2749 alvherre 1423 CBC 293498 : if (!replorigin || replorigin_session_origin_timestamp == 0)
177 andres 1424 GNC 292741 : replorigin_session_origin_timestamp = GetCurrentTransactionStopTimestamp();
2749 alvherre 1425 ECB :
3049 alvherre 1426 GIC 293498 : TransactionTreeSetCommitTsData(xid, nchildren, children,
1427 : replorigin_session_origin_timestamp,
1428 : replorigin_session_origin);
1429 : }
1430 :
1431 : /*
1432 : * Check if we want to commit asynchronously. We can allow the XLOG flush
1433 : * to happen asynchronously if synchronous_commit=off, or if the current
1434 : * transaction has not performed any WAL-logged operation or didn't assign
1435 : * an xid. The transaction can end up not writing any WAL, even if it has
1436 : * an xid, if it only wrote to temporary and/or unlogged tables. It can
1437 : * end up having written WAL without an xid if it did HOT pruning. In
1438 : * case of a crash, the loss of such a transaction will be irrelevant;
1439 : * temp tables will be lost anyway, unlogged tables will be truncated and
1440 : * HOT pruning will be done again later. (Given the foregoing, you might
1441 : * think that it would be unnecessary to emit the XLOG record at all in
1442 : * this case, but we don't currently try to do that. It would certainly
1443 : * cause problems at least in Hot Standby mode, where the
1444 : * KnownAssignedXids machinery requires tracking every XID assignment. It
1445 : * might be OK to skip it only when wal_level < replica, but for now we
1446 : * don't.)
1447 : *
1448 : * However, if we're doing cleanup of any non-temp rels or committing any
1449 : * command that wanted to force sync commit, then we must flush XLOG
1450 : * immediately. (We must not allow asynchronous commit if there are any
1451 : * non-temp tables to be deleted, because we might delete the files before
1452 : * the COMMIT record is flushed to disk. We do allow asynchronous commit
1453 : * if all to-be-deleted tables are temporary though, since they are lost
1454 : * anyway if we crash.)
5695 tgl 1455 ECB : */
2964 andres 1456 CBC 341153 : if ((wrote_xlog && markXidCommitted &&
1457 341153 : synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
4388 rhaas 1458 GIC 54637 : forceSyncCommit || nrels > 0)
5695 tgl 1459 ECB : {
5695 tgl 1460 GIC 286533 : XLogFlush(XactLastRecEnd);
1461 :
1462 : /*
1463 : * Now we may update the CLOG, if we wrote a COMMIT record above
5695 tgl 1464 ECB : */
5695 tgl 1465 CBC 286533 : if (markXidCommitted)
5284 alvherre 1466 GIC 286533 : TransactionIdCommitTree(xid, nchildren, children);
1467 : }
1468 : else
1469 : {
1470 : /*
1471 : * Asynchronous commit case:
1472 : *
1473 : * This enables possible committed transaction loss in the case of a
1474 : * postmaster crash because WAL buffers are left unwritten. Ideally we
1475 : * could issue the WAL write without the fsync, but some
1476 : * wal_sync_methods do not allow separate write/fsync.
1477 : *
1478 : * Report the latest async commit LSN, so that the WAL writer knows to
1479 : * flush this commit.
7551 tgl 1480 ECB : */
4637 simon 1481 GIC 54620 : XLogSetAsyncXactLSN(XactLastRecEnd);
1482 :
1483 : /*
1484 : * We must not immediately update the CLOG, since we didn't flush the
1485 : * XLOG. Instead, we store the LSN up to which the XLOG must be
1486 : * flushed before the CLOG may be updated.
5695 tgl 1487 ECB : */
5695 tgl 1488 CBC 54620 : if (markXidCommitted)
5284 alvherre 1489 GIC 6965 : TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
1490 : }
1491 :
1492 : /*
1493 : * If we entered a commit critical section, leave it now, and let
1494 : * checkpoints proceed.
5695 tgl 1495 ECB : */
5695 tgl 1496 GIC 341153 : if (markXidCommitted)
5695 tgl 1497 ECB : {
366 rhaas 1498 CBC 293498 : MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
8122 tgl 1499 GIC 293498 : END_CRIT_SECTION();
1500 : }
1501 :
5692 tgl 1502 ECB : /* Compute latestXid while we have the child XIDs handy */
5692 tgl 1503 GIC 341153 : latestXid = TransactionIdLatest(xid, nchildren, children);
1504 :
1505 : /*
1506 : * Wait for synchronous replication, if required. Similar to the decision
1507 : * above about using committing asynchronously we only want to wait if
1508 : * this backend assigned an xid and wrote WAL. No need to wait if an xid
1509 : * was assigned due to temporary/unlogged tables or due to HOT pruning.
1510 : *
1511 : * Note that at this stage we have marked clog, but still show as running
1512 : * in the procarray and continue to hold locks.
4417 simon 1513 ECB : */
2964 andres 1514 CBC 341153 : if (wrote_xlog && markXidCommitted)
2567 rhaas 1515 GIC 289582 : SyncRepWaitForLSN(XactLastRecEnd, true);
1516 :
2902 andres 1517 ECB : /* remember end of last commit record */
2902 andres 1518 GIC 341153 : XactLastCommitEnd = XactLastRecEnd;
1519 :
5695 tgl 1520 ECB : /* Reset XactLastRecEnd until the next transaction writes something */
3941 heikki.linnakangas 1521 CBC 341153 : XactLastRecEnd = 0;
5695 tgl 1522 GIC 463648 : cleanup:
5695 tgl 1523 ECB : /* Clean up local data */
6505 tgl 1524 CBC 463648 : if (rels)
1525 7391 : pfree(rels);
368 andres 1526 463648 : if (ndroppedstats)
368 andres 1527 GIC 8934 : pfree(droppedstats);
5692 tgl 1528 ECB :
5692 tgl 1529 GIC 463648 : return latestXid;
1530 : }
1531 :
1532 :
1533 : /*
1534 : * AtCCI_LocalCache
1535 : */
8490 inoue 1536 ECB : static void
4809 tgl 1537 GIC 1206274 : AtCCI_LocalCache(void)
1538 : {
1539 : /*
1540 : * Make any pending relation map changes visible. We must do this before
1541 : * processing local sinval messages, so that the map changes will get
1542 : * reflected into the relcache when relcache invals are processed.
4809 tgl 1543 ECB : */
4809 tgl 1544 GIC 1206274 : AtCCI_RelationMap();
1545 :
1546 : /*
1547 : * Make catalog changes visible to me for the next command.
8490 inoue 1548 ECB : */
6856 tgl 1549 CBC 1206274 : CommandEndInvalidationMessages();
8490 inoue 1550 GIC 1206271 : }
1551 :
1552 : /*
1553 : * AtCommit_Memory
1554 : */
9364 bruce 1555 ECB : static void
8202 tgl 1556 GIC 465297 : AtCommit_Memory(void)
1557 : {
1558 : /*
1559 : * Now that we're "out" of a transaction, have the system allocate things
1560 : * in the top memory context instead of per-transaction contexts.
8732 tgl 1561 ECB : */
8320 tgl 1562 GIC 465297 : MemoryContextSwitchTo(TopMemoryContext);
1563 :
1564 : /*
1565 : * Release all transaction-local memory.
9345 bruce 1566 ECB : */
8316 tgl 1567 CBC 465297 : Assert(TopTransactionContext != NULL);
8320 1568 465297 : MemoryContextDelete(TopTransactionContext);
1569 465297 : TopTransactionContext = NULL;
6856 1570 465297 : CurTransactionContext = NULL;
1571 465297 : CurrentTransactionState->curTransactionContext = NULL;
6856 tgl 1572 GIC 465297 : }
1573 :
1574 : /* ----------------------------------------------------------------
1575 : * CommitSubTransaction stuff
1576 : * ----------------------------------------------------------------
1577 : */
1578 :
1579 : /*
1580 : * AtSubCommit_Memory
1581 : */
6856 tgl 1582 ECB : static void
6856 tgl 1583 GIC 4315 : AtSubCommit_Memory(void)
6856 tgl 1584 ECB : {
6856 tgl 1585 GIC 4315 : TransactionState s = CurrentTransactionState;
6856 tgl 1586 ECB :
6856 tgl 1587 GIC 4315 : Assert(s->parent != NULL);
1588 :
6856 tgl 1589 ECB : /* Return to parent transaction level's memory context. */
6856 tgl 1590 CBC 4315 : CurTransactionContext = s->parent->curTransactionContext;
6856 tgl 1591 GIC 4315 : MemoryContextSwitchTo(CurTransactionContext);
1592 :
1593 : /*
1594 : * Ordinarily we cannot throw away the child's CurTransactionContext,
1595 : * since the data it contains will be needed at upper commit. However, if
1596 : * there isn't actually anything in it, we can throw it away. This avoids
1597 : * a small memory leak in the common case of "trivial" subxacts.
6779 tgl 1598 ECB : */
6779 tgl 1599 GIC 4315 : if (MemoryContextIsEmpty(s->curTransactionContext))
6779 tgl 1600 ECB : {
6779 tgl 1601 CBC 4301 : MemoryContextDelete(s->curTransactionContext);
6779 tgl 1602 GIC 4301 : s->curTransactionContext = NULL;
6779 tgl 1603 ECB : }
6856 tgl 1604 GIC 4315 : }
1605 :
1606 : /*
1607 : * AtSubCommit_childXids
1608 : *
1609 : * Pass my own XID and my child XIDs up to my parent as committed children.
1610 : */
6856 tgl 1611 ECB : static void
6856 tgl 1612 GIC 2804 : AtSubCommit_childXids(void)
6856 tgl 1613 ECB : {
6856 tgl 1614 GIC 2804 : TransactionState s = CurrentTransactionState;
1615 : int new_nChildXids;
6856 tgl 1616 ECB :
6856 tgl 1617 GIC 2804 : Assert(s->parent != NULL);
1618 :
1619 : /*
1620 : * The parent childXids array will need to hold my XID and all my
1621 : * childXids, in addition to the XIDs already there.
6779 tgl 1622 ECB : */
5501 tgl 1623 GIC 2804 : new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
1624 :
5501 tgl 1625 ECB : /* Allocate or enlarge the parent array if necessary */
5501 tgl 1626 GIC 2804 : if (s->parent->maxChildXids < new_nChildXids)
1627 : {
1628 : int new_maxChildXids;
1629 : TransactionId *new_childXids;
1630 :
1631 : /*
1632 : * Make it 2x what's needed right now, to avoid having to enlarge it
1633 : * repeatedly. But we can't go above MaxAllocSize. (The latter limit
1634 : * is what ensures that we don't need to worry about integer overflow
1635 : * here or in the calculation of new_nChildXids.)
6779 tgl 1636 ECB : */
5501 tgl 1637 GIC 1673 : new_maxChildXids = Min(new_nChildXids * 2,
1638 : (int) (MaxAllocSize / sizeof(TransactionId)));
5501 tgl 1639 ECB :
5501 tgl 1640 GBC 1673 : if (new_maxChildXids < new_nChildXids)
5501 tgl 1641 UIC 0 : ereport(ERROR,
1642 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1643 : errmsg("maximum number of committed subtransactions (%d) exceeded",
1644 : (int) (MaxAllocSize / sizeof(TransactionId)))));
1645 :
1646 : /*
1647 : * We keep the child-XID arrays in TopTransactionContext; this avoids
1648 : * setting up child-transaction contexts for what might be just a few
1649 : * bytes of grandchild XIDs.
5501 tgl 1650 ECB : */
5501 tgl 1651 GIC 1673 : if (s->parent->childXids == NULL)
5501 tgl 1652 ECB : new_childXids =
5050 bruce 1653 GIC 1642 : MemoryContextAlloc(TopTransactionContext,
1654 : new_maxChildXids * sizeof(TransactionId));
5501 tgl 1655 ECB : else
5050 bruce 1656 GIC 31 : new_childXids = repalloc(s->parent->childXids,
1657 : new_maxChildXids * sizeof(TransactionId));
5501 tgl 1658 ECB :
5050 bruce 1659 CBC 1673 : s->parent->childXids = new_childXids;
5501 tgl 1660 GIC 1673 : s->parent->maxChildXids = new_maxChildXids;
1661 : }
1662 :
1663 : /*
1664 : * Copy all my XIDs to parent's array.
1665 : *
1666 : * Note: We rely on the fact that the XID of a child always follows that
1667 : * of its parent. By copying the XID of this subtransaction before the
1668 : * XIDs of its children, we ensure that the array stays ordered. Likewise,
1669 : * all XIDs already in the array belong to subtransactions started and
1670 : * subcommitted before us, so their XIDs must precede ours.
5501 tgl 1671 ECB : */
1473 tmunro 1672 GIC 2804 : s->parent->childXids[s->parent->nChildXids] = XidFromFullTransactionId(s->fullTransactionId);
5501 tgl 1673 ECB :
5501 tgl 1674 CBC 2804 : if (s->nChildXids > 0)
1675 1008 : memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
1676 1008 : s->childXids,
5501 tgl 1677 GIC 1008 : s->nChildXids * sizeof(TransactionId));
5501 tgl 1678 ECB :
5501 tgl 1679 GIC 2804 : s->parent->nChildXids = new_nChildXids;
1680 :
5501 tgl 1681 ECB : /* Release child's array to avoid leakage */
5501 tgl 1682 CBC 2804 : if (s->childXids != NULL)
5501 tgl 1683 GIC 1008 : pfree(s->childXids);
5501 tgl 1684 ECB : /* We must reset these to avoid double-free if fail later in commit */
5501 tgl 1685 CBC 2804 : s->childXids = NULL;
1686 2804 : s->nChildXids = 0;
1687 2804 : s->maxChildXids = 0;
6856 tgl 1688 GIC 2804 : }
1689 :
1690 : /* ----------------------------------------------------------------
1691 : * AbortTransaction stuff
1692 : * ----------------------------------------------------------------
1693 : */
1694 :
1695 : /*
1696 : * RecordTransactionAbort
1697 : *
1698 : * Returns latest XID among xact and its children, or InvalidTransactionId
1699 : * if the xact has no XID. (We compute that here just because it's easier.)
1700 : */
5692 tgl 1701 ECB : static TransactionId
5695 tgl 1702 GIC 24563 : RecordTransactionAbort(bool isSubXact)
9770 scrappy 1703 ECB : {
5695 tgl 1704 GIC 24563 : TransactionId xid = GetCurrentTransactionIdIfAny();
1705 : TransactionId latestXid;
1706 : int nrels;
1707 : RelFileLocator *rels;
368 andres 1708 CBC 24563 : int ndroppedstats = 0;
368 andres 1709 GIC 24563 : xl_xact_stats_item *droppedstats = NULL;
1710 : int nchildren;
1711 : TransactionId *children;
1712 : TimestampTz xact_time;
1713 : bool replorigin;
1714 :
1715 : /*
1716 : * If we haven't been assigned an XID, nobody will care whether we aborted
1717 : * or not. Hence, we're done in that case. It does not matter if we have
1718 : * rels to delete (note that this routine is not responsible for actually
1719 : * deleting 'em). We cannot have any child XIDs, either.
1720 : */
5695 tgl 1721 CBC 24563 : if (!TransactionIdIsValid(xid))
1722 : {
1723 : /* Reset XactLastRecEnd until the next transaction writes something */
1724 19783 : if (!isSubXact)
3941 heikki.linnakangas 1725 15925 : XactLastRecEnd = 0;
5692 tgl 1726 19783 : return InvalidTransactionId;
1727 : }
1728 :
1729 : /*
1730 : * We have a valid XID, so we should write an ABORT record for it.
1731 : *
1732 : * We do not flush XLOG to disk here, since the default assumption after a
1733 : * crash would be that we aborted, anyway. For the same reason, we don't
1734 : * need to worry about interlocking against checkpoint start.
1735 : */
1736 :
1737 : /*
1738 : * Check that we haven't aborted halfway through RecordTransactionCommit.
1739 : */
5695 1740 4780 : if (TransactionIdDidCommit(xid))
5695 tgl 1741 UBC 0 : elog(PANIC, "cannot abort transaction %u, it was already committed",
1742 : xid);
1743 :
1744 : /*
1745 : * Are we using the replication origins feature? Or, in other words, are
1746 : * we replaying remote actions?
1747 : */
90 akapila 1748 GNC 4812 : replorigin = (replorigin_session_origin != InvalidRepOriginId &&
1749 32 : replorigin_session_origin != DoNotReplicateId);
1750 :
1751 : /* Fetch the data we need for the abort record */
4622 rhaas 1752 GIC 4780 : nrels = smgrGetPendingDeletes(false, &rels);
5695 tgl 1753 4780 : nchildren = xactGetCommittedChildren(&children);
368 andres 1754 4780 : ndroppedstats = pgstat_get_transactional_drops(false, &droppedstats);
7551 tgl 1755 ECB :
5695 1756 : /* XXX do we really need a critical section here? */
5695 tgl 1757 GIC 4780 : START_CRIT_SECTION();
1758 :
5695 tgl 1759 ECB : /* Write the ABORT record */
5695 tgl 1760 CBC 4780 : if (isSubXact)
2947 andres 1761 610 : xact_time = GetCurrentTimestamp();
1762 : else
1763 : {
177 andres 1764 GNC 4170 : xact_time = GetCurrentTransactionStopTimestamp();
1765 : }
3062 heikki.linnakangas 1766 ECB :
2947 andres 1767 CBC 4780 : XactLogAbortRecord(xact_time,
1768 : nchildren, children,
1769 : nrels, rels,
368 andres 1770 ECB : ndroppedstats, droppedstats,
1771 : MyXactFlags, InvalidTransactionId,
1772 : NULL);
8062 tgl 1773 :
90 akapila 1774 GNC 4780 : if (replorigin)
1775 : /* Move LSNs forward for this replication origin */
1776 32 : replorigin_session_advance(replorigin_session_origin_lsn,
1777 : XactLastRecEnd);
1778 :
1779 : /*
1780 : * Report the latest async abort LSN, so that the WAL writer knows to
1781 : * flush this abort. There's nothing to be gained by delaying this, since
1782 : * WALWriter may as well do this when it can. This is important with
1783 : * streaming replication because if we don't flush WAL regularly we will
1784 : * find that large aborts leave us with a long backlog for when commits
4660 bruce 1785 ECB : * occur after the abort, increasing our window of data loss should
1786 : * problems occur at that point.
4714 simon 1787 : */
4714 simon 1788 GIC 4780 : if (!isSubXact)
4637 1789 4170 : XLogSetAsyncXactLSN(XactLastRecEnd);
1790 :
1791 : /*
1792 : * Mark the transaction aborted in clog. This is not absolutely necessary
1793 : * but we may as well do it while we are here; also, in the subxact case
1794 : * it is helpful because XactLockTableWait makes use of it to avoid
1795 : * waiting for already-aborted subtransactions. It is OK to do it without
1796 : * having flushed the ABORT record to disk, because in event of a crash
1797 : * we'd be assumed to have aborted anyway.
1798 : */
5284 alvherre 1799 CBC 4780 : TransactionIdAbortTree(xid, nchildren, children);
8206 vadim4o 1800 ECB :
5695 tgl 1801 GIC 4780 : END_CRIT_SECTION();
1802 :
1803 : /* Compute latestXid while we have the child XIDs handy */
5692 1804 4780 : latestXid = TransactionIdLatest(xid, nchildren, children);
1805 :
1806 : /*
1807 : * If we're aborting a subtransaction, we can immediately remove failed
1808 : * XIDs from PGPROC's cache of running child XIDs. We do that here for
1809 : * subxacts, because we already have the child XID array at hand. For
5695 tgl 1810 ECB : * main xacts, the equivalent happens just after this function returns.
1811 : */
5695 tgl 1812 CBC 4780 : if (isSubXact)
5692 tgl 1813 GIC 610 : XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
1814 :
5695 tgl 1815 ECB : /* Reset XactLastRecEnd until the next transaction writes something */
5695 tgl 1816 GIC 4780 : if (!isSubXact)
3941 heikki.linnakangas 1817 4170 : XactLastRecEnd = 0;
1818 :
1819 : /* And clean up local data */
6505 tgl 1820 4780 : if (rels)
1821 693 : pfree(rels);
368 andres 1822 4780 : if (ndroppedstats)
368 andres 1823 CBC 967 : pfree(droppedstats);
5692 tgl 1824 ECB :
5692 tgl 1825 GIC 4780 : return latestXid;
1826 : }
9770 scrappy 1827 ECB :
7331 bruce 1828 : /*
1829 : * AtAbort_Memory
1830 : */
9364 1831 : static void
8202 tgl 1832 CBC 31856 : AtAbort_Memory(void)
9770 scrappy 1833 ECB : {
8053 bruce 1834 : /*
1835 : * Switch into TransactionAbortContext, which should have some free space
5624 1836 : * even if nothing else does. We'll work in this context until we've
1837 : * finished cleaning up.
1838 : *
1839 : * It is barely possible to get here when we've not been able to create
1840 : * TransactionAbortContext yet; if so use TopMemoryContext.
1841 : */
5981 tgl 1842 GIC 31856 : if (TransactionAbortContext != NULL)
5981 tgl 1843 CBC 31856 : MemoryContextSwitchTo(TransactionAbortContext);
1844 : else
8316 tgl 1845 UIC 0 : MemoryContextSwitchTo(TopMemoryContext);
8320 tgl 1846 GIC 31856 : }
1847 :
1848 : /*
1849 : * AtSubAbort_Memory
1850 : */
1851 : static void
6856 1852 4468 : AtSubAbort_Memory(void)
6856 tgl 1853 ECB : {
5981 tgl 1854 CBC 4468 : Assert(TransactionAbortContext != NULL);
1855 :
5981 tgl 1856 GBC 4468 : MemoryContextSwitchTo(TransactionAbortContext);
6856 tgl 1857 CBC 4468 : }
1858 :
1859 :
1860 : /*
1861 : * AtAbort_ResourceOwner
1862 : */
6761 tgl 1863 ECB : static void
6761 tgl 1864 GIC 20098 : AtAbort_ResourceOwner(void)
6761 tgl 1865 ECB : {
1866 : /*
6385 bruce 1867 : * Make sure we have a valid ResourceOwner, if possible (else it will be
1868 : * NULL, which is OK)
1869 : */
6761 tgl 1870 GIC 20098 : CurrentResourceOwner = TopTransactionResourceOwner;
1871 20098 : }
1872 :
1873 : /*
1874 : * AtSubAbort_ResourceOwner
6761 tgl 1875 ECB : */
1876 : static void
6761 tgl 1877 GIC 4468 : AtSubAbort_ResourceOwner(void)
1878 : {
1879 4468 : TransactionState s = CurrentTransactionState;
1880 :
6761 tgl 1881 ECB : /* Make sure we have a valid ResourceOwner */
6761 tgl 1882 CBC 4468 : CurrentResourceOwner = s->curTransactionOwner;
6761 tgl 1883 GIC 4468 : }
1884 :
1885 :
1886 : /*
1887 : * AtSubAbort_childXids
6779 tgl 1888 ECB : */
1889 : static void
6779 tgl 1890 CBC 610 : AtSubAbort_childXids(void)
1891 : {
6779 tgl 1892 GIC 610 : TransactionState s = CurrentTransactionState;
6779 tgl 1893 ECB :
1894 : /*
1895 : * We keep the child-XID arrays in TopTransactionContext (see
1896 : * AtSubCommit_childXids). This means we'd better free the array
1897 : * explicitly at abort to avoid leakage.
1898 : */
5501 tgl 1899 GIC 610 : if (s->childXids != NULL)
1900 25 : pfree(s->childXids);
5501 tgl 1901 CBC 610 : s->childXids = NULL;
5501 tgl 1902 GIC 610 : s->nChildXids = 0;
5501 tgl 1903 CBC 610 : s->maxChildXids = 0;
1904 :
1905 : /*
1906 : * We could prune the unreportedXids array here. But we don't bother. That
1907 : * would potentially reduce number of XLOG_XACT_ASSIGNMENT records but it
1908 : * would likely introduce more CPU time into the more common paths, so we
1909 : * choose not to do that.
4859 simon 1910 ECB : */
6779 tgl 1911 CBC 610 : }
6779 tgl 1912 ECB :
8320 1913 : /* ----------------------------------------------------------------
1914 : * CleanupTransaction stuff
1915 : * ----------------------------------------------------------------
1916 : */
1917 :
1918 : /*
1919 : * AtCleanup_Memory
1920 : */
1921 : static void
8202 tgl 1922 CBC 31856 : AtCleanup_Memory(void)
1923 : {
5981 tgl 1924 GIC 31856 : Assert(CurrentTransactionState->parent == NULL);
1925 :
1926 : /*
1927 : * Now that we're "out" of a transaction, have the system allocate things
1928 : * in the top memory context instead of per-transaction contexts.
1929 : */
9345 bruce 1930 31856 : MemoryContextSwitchTo(TopMemoryContext);
1931 :
1932 : /*
5981 tgl 1933 ECB : * Clear the special abort context for next time.
1934 : */
5981 tgl 1935 CBC 31856 : if (TransactionAbortContext != NULL)
5981 tgl 1936 GIC 31856 : MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1937 :
1938 : /*
1939 : * Release all transaction-local memory.
1940 : */
8316 tgl 1941 CBC 31856 : if (TopTransactionContext != NULL)
8316 tgl 1942 GIC 20098 : MemoryContextDelete(TopTransactionContext);
8320 1943 31856 : TopTransactionContext = NULL;
6856 1944 31856 : CurTransactionContext = NULL;
1945 31856 : CurrentTransactionState->curTransactionContext = NULL;
9770 scrappy 1946 CBC 31856 : }
9770 scrappy 1947 ECB :
1948 :
1949 : /* ----------------------------------------------------------------
1950 : * CleanupSubTransaction stuff
1951 : * ----------------------------------------------------------------
6856 tgl 1952 : */
1953 :
1954 : /*
1955 : * AtSubCleanup_Memory
1956 : */
1957 : static void
6856 tgl 1958 GIC 4468 : AtSubCleanup_Memory(void)
1959 : {
1960 4468 : TransactionState s = CurrentTransactionState;
1961 :
1962 4468 : Assert(s->parent != NULL);
1963 :
1964 : /* Make sure we're not in an about-to-be-deleted context */
1965 4468 : MemoryContextSwitchTo(s->parent->curTransactionContext);
1966 4468 : CurTransactionContext = s->parent->curTransactionContext;
1967 :
1968 : /*
5981 tgl 1969 ECB : * Clear the special abort context for next time.
1970 : */
5981 tgl 1971 CBC 4468 : if (TransactionAbortContext != NULL)
5981 tgl 1972 GIC 4468 : MemoryContextResetAndDeleteChildren(TransactionAbortContext);
5981 tgl 1973 ECB :
1974 : /*
1975 : * Delete the subxact local memory contexts. Its CurTransactionContext can
6385 bruce 1976 : * go too (note this also kills CurTransactionContexts from any children
1977 : * of the subxact).
1978 : */
6779 tgl 1979 GIC 4468 : if (s->curTransactionContext)
1980 4468 : MemoryContextDelete(s->curTransactionContext);
1981 4468 : s->curTransactionContext = NULL;
6856 tgl 1982 CBC 4468 : }
6856 tgl 1983 ECB :
1984 : /* ----------------------------------------------------------------
1985 : * interface routines
1986 : * ----------------------------------------------------------------
1987 : */
1988 :
1989 : /*
7452 bruce 1990 : * StartTransaction
9770 scrappy 1991 : */
9364 bruce 1992 : static void
8202 tgl 1993 CBC 485395 : StartTransaction(void)
1994 : {
1995 : TransactionState s;
1996 : VirtualTransactionId vxid;
1997 :
1998 : /*
1999 : * Let's just make sure the state stack is empty
2000 : */
6779 tgl 2001 GIC 485395 : s = &TopTransactionStateData;
2002 485395 : CurrentTransactionState = s;
2003 :
1473 tmunro 2004 CBC 485395 : Assert(!FullTransactionIdIsValid(XactTopFullTransactionId));
2005 :
2006 : /* check the current transaction state */
1607 michael 2007 GIC 485395 : Assert(s->state == TRANS_DEFAULT);
2008 :
2009 : /*
2010 : * Set the current transaction state information appropriately during
2011 : * start processing. Note that once the transaction status is switched
1607 michael 2012 ECB : * this process cannot fail until the user ID and the security context
2013 : * flags are fetched below.
2014 : */
9345 bruce 2015 CBC 485395 : s->state = TRANS_START;
1473 tmunro 2016 GIC 485395 : s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
2017 :
1467 alvherre 2018 ECB : /* Determine if statements are logged in this transaction */
1467 alvherre 2019 GIC 485395 : xact_is_sampled = log_xact_sample_rate != 0 &&
1467 alvherre 2020 UIC 0 : (log_xact_sample_rate == 1 ||
497 tgl 2021 0 : pg_prng_double(&pg_global_prng_state) <= log_xact_sample_rate);
2022 :
2023 : /*
2024 : * initialize current transaction state fields
2025 : *
1607 michael 2026 ECB : * note: prevXactReadOnly is not used at the outermost level
2027 : */
1607 michael 2028 GIC 485395 : s->nestingLevel = 1;
2029 485395 : s->gucNestLevel = 1;
1607 michael 2030 CBC 485395 : s->childXids = NULL;
1607 michael 2031 GBC 485395 : s->nChildXids = 0;
2032 485395 : s->maxChildXids = 0;
2033 :
2034 : /*
2035 : * Once the current user ID and the security context flags are fetched,
2036 : * both will be properly reset even if transaction startup fails.
2037 : */
1607 michael 2038 GIC 485395 : GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
1607 michael 2039 ECB :
2040 : /* SecurityRestrictionContext should never be set outside a transaction */
1607 michael 2041 CBC 485395 : Assert(s->prevSecContext == 0);
1607 michael 2042 ECB :
7115 tgl 2043 : /*
2044 : * Make sure we've reset xact state variables
2045 : *
2046 : * If recovery is still in progress, mark this transaction as read-only.
2047 : * We have lower level defences in XLogInsert and elsewhere to stop us
2048 : * from modifying data during recovery, but this gives the normal
4859 simon 2049 : * indication to the user that the transaction is read-only.
2050 : */
4859 simon 2051 GIC 485395 : if (RecoveryInProgress())
4859 simon 2052 ECB : {
4859 simon 2053 GIC 1149 : s->startedInRecovery = true;
2054 1149 : XactReadOnly = true;
2055 : }
2056 : else
2057 : {
2058 484246 : s->startedInRecovery = false;
2059 484246 : XactReadOnly = DefaultXactReadOnly;
2060 : }
4444 heikki.linnakangas 2061 485395 : XactDeferrable = DefaultXactDeferrable;
7115 tgl 2062 CBC 485395 : XactIsoLevel = DefaultXactIsoLevel;
5730 tgl 2063 GIC 485395 : forceSyncCommit = false;
2209 simon 2064 CBC 485395 : MyXactFlags = 0;
7115 tgl 2065 ECB :
2066 : /*
2067 : * reinitialize within-transaction counters
2068 : */
6779 tgl 2069 CBC 485395 : s->subTransactionId = TopSubTransactionId;
2070 485395 : currentSubTransactionId = TopSubTransactionId;
6779 tgl 2071 GIC 485395 : currentCommandId = FirstCommandId;
5609 tgl 2072 CBC 485395 : currentCommandIdUsed = false;
6779 tgl 2073 ECB :
4859 simon 2074 : /*
2075 : * initialize reported xid accounting
2076 : */
4859 simon 2077 GIC 485395 : nUnreportedXids = 0;
3407 rhaas 2078 485395 : s->didLogXid = false;
2079 :
6840 tgl 2080 ECB : /*
2081 : * must initialize resource-management stuff first
2082 : */
6840 tgl 2083 CBC 485395 : AtStart_Memory();
6840 tgl 2084 GIC 485395 : AtStart_ResourceOwner();
2085 :
2086 : /*
2087 : * Assign a new LocalTransactionId, and combine it with the backendId to
5695 tgl 2088 ECB : * form a virtual transaction id.
2089 : */
5695 tgl 2090 GIC 485395 : vxid.backendId = MyBackendId;
2091 485395 : vxid.localTransactionId = GetNextLocalTransactionId();
2092 :
2093 : /*
5695 tgl 2094 ECB : * Lock the virtual transaction id before we announce it in the proc array
9345 bruce 2095 : */
5695 tgl 2096 GIC 485395 : VirtualXactLockTableInsert(vxid);
2097 :
2098 : /*
2099 : * Advertise it in the proc array. We assume assignment of
2100 : * localTransactionId is atomic, and the backendId should be set already.
5695 tgl 2101 ECB : */
5695 tgl 2102 CBC 485395 : Assert(MyProc->backendId == vxid.backendId);
5695 tgl 2103 GIC 485395 : MyProc->lxid = vxid.localTransactionId;
2104 :
2105 : TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
2106 :
6856 tgl 2107 ECB : /*
2108 : * set transaction_timestamp() (a/k/a now()). Normally, we want this to
2109 : * be the same as the first command's statement_timestamp(), so don't do a
2110 : * fresh GetCurrentTimestamp() call (which'd be expensive anyway). But
2111 : * for transactions started inside procedures (i.e., nonatomic SPI
2112 : * contexts), we do need to advance the timestamp. Also, in a parallel
1644 2113 : * worker, the timestamp should already have been provided by a call to
1646 2114 : * SetParallelStartTimestamps().
2115 : */
1646 tgl 2116 GIC 485395 : if (!IsParallelWorker())
2117 : {
1644 2118 481501 : if (!SPI_inside_nonatomic_context())
2119 479298 : xactStartTimestamp = stmtStartTimestamp;
2120 : else
2121 2203 : xactStartTimestamp = GetCurrentTimestamp();
2122 : }
2123 : else
1646 2124 3894 : Assert(xactStartTimestamp != 0);
5689 2125 485395 : pgstat_report_xact_timestamp(xactStartTimestamp);
2126 : /* Mark xactStopTimestamp as unset. */
1644 tgl 2127 CBC 485395 : xactStopTimestamp = 0;
2128 :
8053 bruce 2129 ECB : /*
6840 tgl 2130 : * initialize other subsystems for new transaction
2131 : */
5697 tgl 2132 CBC 485395 : AtStart_GUC();
9345 bruce 2133 GIC 485395 : AtStart_Cache();
6785 tgl 2134 485395 : AfterTriggerBeginXact();
8593 JanWieck 2135 ECB :
8053 bruce 2136 : /*
2137 : * done with start processing, set current transaction state to "in
2138 : * progress"
2139 : */
9345 bruce 2140 GIC 485395 : s->state = TRANS_INPROGRESS;
2141 :
6856 tgl 2142 485395 : ShowTransactionState("StartTransaction");
9770 scrappy 2143 CBC 485395 : }
9770 scrappy 2144 ECB :
6505 tgl 2145 :
2146 : /*
2147 : * CommitTransaction
2148 : *
2149 : * NB: if you change this routine, better look at PrepareTransaction too!
2150 : */
9364 bruce 2151 : static void
8202 tgl 2152 GIC 465157 : CommitTransaction(void)
9770 scrappy 2153 ECB : {
9345 bruce 2154 CBC 465157 : TransactionState s = CurrentTransactionState;
2155 : TransactionId latestXid;
2156 : bool is_parallel_worker;
2157 :
2901 rhaas 2158 GIC 465157 : is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
2159 :
2160 : /* Enforce parallel mode restrictions during parallel worker commit. */
2732 2161 465157 : if (is_parallel_worker)
2162 1295 : EnterParallelMode();
2732 rhaas 2163 ECB :
6856 tgl 2164 GIC 465157 : ShowTransactionState("CommitTransaction");
6856 tgl 2165 ECB :
2166 : /*
2167 : * check the current transaction state
2168 : */
9345 bruce 2169 CBC 465157 : if (s->state != TRANS_INPROGRESS)
6829 tgl 2170 UIC 0 : elog(WARNING, "CommitTransaction while in %s state",
2171 : TransStateAsString(s->state));
6856 tgl 2172 CBC 465157 : Assert(s->parent == NULL);
9345 bruce 2173 ECB :
2174 : /*
4424 tgl 2175 : * Do pre-commit processing that involves calling user-defined code, such
2176 : * as triggers. SECURITY_RESTRICTED_OPERATION contexts must not queue an
2177 : * action that would run here, because that would bypass the sandbox.
2178 : * Since closing cursors could queue trigger actions, triggers could open
2179 : * cursors, etc, we have to keep looping until there's nothing left to do.
6736 2180 : */
6572 tgl 2181 EUB : for (;;)
2182 : {
6572 tgl 2183 ECB : /*
2184 : * Fire all currently pending deferred triggers.
2185 : */
6572 tgl 2186 GIC 470958 : AfterTriggerFireDeferred();
2187 :
2188 : /*
2189 : * Close open portals (converting holdable ones into static portals).
2190 : * If there weren't any, we are done ... otherwise loop back to check
2191 : * if they queued deferred triggers. Lather, rinse, repeat.
2192 : */
4424 2193 470902 : if (!PreCommit_Portals(false))
6572 2194 465101 : break;
2195 : }
2196 :
4424 tgl 2197 ECB : /*
2198 : * The remaining actions cannot call any user-defined code, so it's safe
2199 : * to start shutting down within-transaction services. But note that most
2200 : * of this stuff could still throw an error, which would switch us into
2201 : * the transaction-abort path.
2202 : */
2203 :
881 noah 2204 CBC 465101 : CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
881 noah 2205 ECB : : XACT_EVENT_PRE_COMMIT);
2206 :
2207 : /* If we might have parallel workers, clean them up now. */
2901 rhaas 2208 GIC 465101 : if (IsInParallelMode())
2209 1295 : AtEOXact_Parallel(true);
2210 :
2211 : /* Shut down the deferred-trigger manager */
4424 tgl 2212 465101 : AfterTriggerEndXact(true);
2213 :
2214 : /*
6736 tgl 2215 ECB : * Let ON COMMIT management do its thing (must happen after closing
2216 : * cursors, to avoid dangling-reference problems)
2217 : */
6736 tgl 2218 GIC 465101 : PreCommit_on_commit_actions();
7475 tgl 2219 ECB :
1100 noah 2220 : /*
2221 : * Synchronize files that are created and not WAL-logged during this
2222 : * transaction. This must happen before AtEOXact_RelationMap(), so that we
2223 : * don't see committed-but-broken files after a crash.
2224 : */
1100 noah 2225 GIC 465098 : smgrDoPendingSyncs(true, is_parallel_worker);
2226 :
2227 : /* close large objects before lower-level cleanup */
6829 tgl 2228 465098 : AtEOXact_LargeObject(true);
9028 bruce 2229 ECB :
2230 : /*
2231 : * Insert notifications sent by NOTIFY commands into the queue. This
2232 : * should be late in the pre-commit sequence to minimize time spent
2233 : * holding the notify-insertion lock. However, this could result in
2234 : * creating a snapshot, so we must do it before serializable cleanup.
2235 : */
1232 tgl 2236 CBC 465098 : PreCommit_Notify();
2237 :
2238 : /*
4444 heikki.linnakangas 2239 ECB : * Mark serializable transaction as complete for predicate locking
2240 : * purposes. This should be done as late as we can put it and still allow
2241 : * errors to be raised for failure patterns found at commit. This is not
2242 : * appropriate in a parallel worker however, because we aren't committing
2243 : * the leader's transaction and its serializable state will live on.
2244 : */
1486 tmunro 2245 GIC 465098 : if (!is_parallel_worker)
2246 463803 : PreCommit_CheckForSerializationFailure();
4444 heikki.linnakangas 2247 ECB :
2248 : /* Prevent cancel/die interrupt while cleaning up */
6736 tgl 2249 GIC 464943 : HOLD_INTERRUPTS();
2250 :
2251 : /* Commit updates to the relation map --- do this as late as possible */
1703 pg 2252 464943 : AtEOXact_RelationMap(true, is_parallel_worker);
2253 :
2254 : /*
2255 : * set the current transaction state information appropriately during
6479 tgl 2256 ECB : * commit processing
6736 2257 : */
6736 tgl 2258 GIC 464943 : s->state = TRANS_COMMIT;
2732 rhaas 2259 464943 : s->parallelModeLevel = 0;
6736 tgl 2260 ECB :
2901 rhaas 2261 GIC 464943 : if (!is_parallel_worker)
2262 : {
2901 rhaas 2263 ECB : /*
2264 : * We need to mark our XIDs as committed in pg_xact. This is where we
2265 : * durably commit.
2266 : */
2901 rhaas 2267 GIC 463648 : latestXid = RecordTransactionCommit();
2268 : }
2901 rhaas 2269 ECB : else
2270 : {
2271 : /*
1029 andres 2272 : * We must not mark our XID committed; the parallel leader is
2273 : * responsible for that.
2274 : */
2901 rhaas 2275 GIC 1295 : latestXid = InvalidTransactionId;
2276 :
2277 : /*
1029 andres 2278 ECB : * Make sure the leader will know about any WAL we wrote before it
2279 : * commits.
2280 : */
2901 rhaas 2281 GIC 1295 : ParallelWorkerReportLastRecEnd(XactLastRecEnd);
2282 : }
2283 :
2284 : TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
2285 :
5693 tgl 2286 ECB : /*
2287 : * Let others know about no transaction in progress by me. Note that this
2288 : * must be done _before_ releasing locks we hold and _after_
2289 : * RecordTransactionCommit.
2290 : */
5692 tgl 2291 GIC 464943 : ProcArrayEndTransaction(MyProc, latestXid);
8711 vadim4o 2292 ECB :
2293 : /*
2294 : * This is all post-commit cleanup. Note that if an error is raised here,
2295 : * it's too late to abort the transaction. This should be just
2296 : * noncritical resource releasing.
2297 : *
2298 : * The ordering of operations is not entirely random. The idea is:
2299 : * release resources visible to other backends (eg, files, buffer pins);
2300 : * then release locks; then release backend-local resources. We want to
2301 : * release locks at the point where any backend waiting for us will see
6347 bruce 2302 : * our transaction as being fully cleaned up.
2303 : *
2304 : * Resources that can be associated with individual queries are handled by
2305 : * the ResourceOwner mechanism. The other calls here are for backend-wide
2306 : * state.
2307 : */
2308 :
2901 rhaas 2309 GIC 464943 : CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
2310 : : XACT_EVENT_COMMIT);
2311 :
6840 tgl 2312 464943 : ResourceOwnerRelease(TopTransactionResourceOwner,
2313 : RESOURCE_RELEASE_BEFORE_LOCKS,
2314 : true, true);
2315 :
2316 : /* Check we've released all buffer pins */
6749 2317 464943 : AtEOXact_Buffers(true);
2318 :
2319 : /* Clean up the relation cache */
6453 tgl 2320 CBC 464943 : AtEOXact_RelationCache(true);
2321 :
2322 : /*
6385 bruce 2323 ECB : * Make catalog changes visible to all backends. This has to happen after
2324 : * relcache references are dropped (see comments for
2325 : * AtEOXact_RelationCache), but before locks are released (if anyone is
2326 : * waiting for lock on a relation we've modified, we want them to know
2327 : * about the catalog change before they start using the relation).
6840 tgl 2328 : */
6840 tgl 2329 GIC 464943 : AtEOXact_Inval(true);
2330 :
6555 tgl 2331 CBC 464943 : AtEOXact_MultiXact();
2332 :
6840 tgl 2333 GIC 464943 : ResourceOwnerRelease(TopTransactionResourceOwner,
2334 : RESOURCE_RELEASE_LOCKS,
2335 : true, true);
2336 464943 : ResourceOwnerRelease(TopTransactionResourceOwner,
2337 : RESOURCE_RELEASE_AFTER_LOCKS,
2338 : true, true);
2339 :
3951 rhaas 2340 ECB : /*
2341 : * Likewise, dropping of files deleted during the transaction is best done
2342 : * after releasing relcache and buffer pins. (This is not strictly
2343 : * necessary during commit, since such pins should have been released
2344 : * already, but this ordering is definitely critical during abort.) Since
2345 : * this may take many seconds, also delay until after releasing locks.
2346 : * Other backends will observe the attendant catalog changes and not
2347 : * attempt to access affected files.
2348 : */
3951 rhaas 2349 GIC 464943 : smgrDoPendingDeletes(true);
2350 :
2351 : /*
2352 : * Send out notification signals to other backends (and do other
2353 : * post-commit NOTIFY cleanup). This must not happen until after our
2354 : * transaction is fully done from the viewpoint of other backends.
2355 : */
4800 tgl 2356 464943 : AtCommit_Notify();
2357 :
2358 : /*
2359 : * Everything after this should be purely internal-to-this-backend
572 tgl 2360 ECB : * cleanup.
2361 : */
5697 tgl 2362 GIC 464943 : AtEOXact_GUC(true, 1);
7068 mail 2363 464943 : AtEOXact_SPI(true);
1643 tmunro 2364 464943 : AtEOXact_Enum();
6779 tgl 2365 464943 : AtEOXact_on_commit_actions(true);
2901 rhaas 2366 464943 : AtEOXact_Namespace(true, is_parallel_worker);
3826 tgl 2367 CBC 464943 : AtEOXact_SMgr();
1807 tgl 2368 GIC 464943 : AtEOXact_Files(true);
5903 2369 464943 : AtEOXact_ComboCid();
5827 2370 464943 : AtEOXact_HashTables(true);
1460 akapila 2371 464943 : AtEOXact_PgStat(true, is_parallel_worker);
2194 simon 2372 464943 : AtEOXact_Snapshot(true, false);
2169 peter_e 2373 CBC 464943 : AtEOXact_ApplyLauncher(true);
93 tgl 2374 GNC 464943 : AtEOXact_LogicalRepWorkers(true);
5689 tgl 2375 CBC 464943 : pgstat_report_xact_timestamp(0);
6840 tgl 2376 ECB :
6840 tgl 2377 CBC 464943 : CurrentResourceOwner = NULL;
2378 464943 : ResourceOwnerDelete(TopTransactionResourceOwner);
2379 464943 : s->curTransactionOwner = NULL;
2380 464943 : CurTransactionResourceOwner = NULL;
2381 464943 : TopTransactionResourceOwner = NULL;
6840 tgl 2382 ECB :
7474 tgl 2383 CBC 464943 : AtCommit_Memory();
7961 JanWieck 2384 ECB :
1473 tmunro 2385 CBC 464943 : s->fullTransactionId = InvalidFullTransactionId;
6779 tgl 2386 464943 : s->subTransactionId = InvalidSubTransactionId;
6856 2387 464943 : s->nestingLevel = 0;
5697 tgl 2388 GIC 464943 : s->gucNestLevel = 0;
5501 tgl 2389 CBC 464943 : s->childXids = NULL;
2390 464943 : s->nChildXids = 0;
2391 464943 : s->maxChildXids = 0;
6856 tgl 2392 ECB :
1473 tmunro 2393 CBC 464943 : XactTopFullTransactionId = InvalidFullTransactionId;
2901 rhaas 2394 GIC 464943 : nParallelCurrentXids = 0;
2901 rhaas 2395 ECB :
2396 : /*
8053 bruce 2397 : * done with commit processing, set current transaction state back to
2398 : * default
9770 scrappy 2399 : */
9345 bruce 2400 CBC 464943 : s->state = TRANS_DEFAULT;
8120 tgl 2401 ECB :
8115 tgl 2402 CBC 464943 : RESUME_INTERRUPTS();
9770 scrappy 2403 464943 : }
2404 :
6505 tgl 2405 ECB :
2406 : /*
2407 : * PrepareTransaction
2408 : *
2409 : * NB: if you change this routine, better look at CommitTransaction too!
2410 : */
2411 : static void
6505 tgl 2412 CBC 402 : PrepareTransaction(void)
2413 : {
6385 bruce 2414 402 : TransactionState s = CurrentTransactionState;
2415 402 : TransactionId xid = GetCurrentTransactionId();
2416 : GlobalTransaction gxact;
2417 : TimestampTz prepared_at;
2418 :
2901 rhaas 2419 GIC 402 : Assert(!IsInParallelMode());
2420 :
6505 tgl 2421 402 : ShowTransactionState("PrepareTransaction");
2422 :
2423 : /*
6505 tgl 2424 ECB : * check the current transaction state
2425 : */
6505 tgl 2426 CBC 402 : if (s->state != TRANS_INPROGRESS)
6505 tgl 2427 LBC 0 : elog(WARNING, "PrepareTransaction while in %s state",
2428 : TransStateAsString(s->state));
6505 tgl 2429 GIC 402 : Assert(s->parent == NULL);
2430 :
6505 tgl 2431 ECB : /*
2432 : * Do pre-commit processing that involves calling user-defined code, such
4424 2433 : * as triggers. Since closing cursors could queue trigger actions,
2434 : * triggers could open cursors, etc, we have to keep looping until there's
2435 : * nothing left to do.
2436 : */
2437 : for (;;)
6505 2438 : {
6505 tgl 2439 EUB : /*
2440 : * Fire all currently pending deferred triggers.
6505 tgl 2441 ECB : */
6505 tgl 2442 GIC 405 : AfterTriggerFireDeferred();
2443 :
2444 : /*
2445 : * Close open portals (converting holdable ones into static portals).
2446 : * If there weren't any, we are done ... otherwise loop back to check
2447 : * if they queued deferred triggers. Lather, rinse, repeat.
2448 : */
4424 2449 405 : if (!PreCommit_Portals(true))
6505 2450 402 : break;
2451 : }
2452 :
3706 2453 402 : CallXactCallbacks(XACT_EVENT_PRE_PREPARE);
3706 tgl 2454 ECB :
2455 : /*
2456 : * The remaining actions cannot call any user-defined code, so it's safe
2457 : * to start shutting down within-transaction services. But note that most
2458 : * of this stuff could still throw an error, which would switch us into
2459 : * the transaction-abort path.
2460 : */
6505 2461 :
4424 2462 : /* Shut down the deferred-trigger manager */
4424 tgl 2463 GIC 401 : AfterTriggerEndXact(true);
2464 :
6505 tgl 2465 ECB : /*
2466 : * Let ON COMMIT management do its thing (must happen after closing
2467 : * cursors, to avoid dangling-reference problems)
2468 : */
6505 tgl 2469 GIC 401 : PreCommit_on_commit_actions();
2470 :
2471 : /*
2472 : * Synchronize files that are created and not WAL-logged during this
2473 : * transaction. This must happen before EndPrepare(), so that we don't see
2474 : * committed-but-broken files after a crash and COMMIT PREPARED.
1100 noah 2475 ECB : */
1100 noah 2476 GIC 401 : smgrDoPendingSyncs(true, false);
2477 :
2478 : /* close large objects before lower-level cleanup */
6505 tgl 2479 401 : AtEOXact_LargeObject(true);
2480 :
1232 tgl 2481 ECB : /* NOTIFY requires no work at this point */
2482 :
2483 : /*
2484 : * Mark serializable transaction as complete for predicate locking
2485 : * purposes. This should be done as late as we can put it and still allow
2486 : * errors to be raised for failure patterns found at commit.
2487 : */
4444 heikki.linnakangas 2488 CBC 401 : PreCommit_CheckForSerializationFailure();
2489 :
2490 : /*
5050 bruce 2491 ECB : * Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
2492 : * this transaction. Having the prepared xact hold locks on another
2493 : * backend's temp table seems a bad idea --- for instance it would prevent
2494 : * the backend from exiting. There are other problems too, such as how to
2495 : * clean up the source backend's local buffers and ON COMMIT state if the
2496 : * prepared xact includes a DROP of a temp table.
2497 : *
2498 : * Other objects types, like functions, operators or extensions, share the
2499 : * same restriction as they should not be created, locked or dropped as
1534 michael 2500 : * this can mess up with this session or even a follow-up session trying
2501 : * to use the same temporary namespace.
2502 : *
2503 : * We must check this after executing any ON COMMIT actions, because they
2504 : * might still access a temp relation.
2505 : *
2506 : * XXX In principle this could be relaxed to allow some useful special
2507 : * cases, such as a temp table created and dropped all within the
2508 : * transaction. That seems to require much more bookkeeping though.
2509 : */
1542 michael 2510 GIC 401 : if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPNAMESPACE))
2511 34 : ereport(ERROR,
2512 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2513 : errmsg("cannot PREPARE a transaction that has operated on temporary objects")));
2514 :
2515 : /*
2516 : * Likewise, don't allow PREPARE after pg_export_snapshot. This could be
2517 : * supported if we added cleanup logic to twophase.c, but for now it
2518 : * doesn't seem worth the trouble.
2519 : */
4187 tgl 2520 367 : if (XactHasExportedSnapshots())
4187 tgl 2521 UIC 0 : ereport(ERROR,
4187 tgl 2522 ECB : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2118 2523 : errmsg("cannot PREPARE a transaction that has exported snapshots")));
2524 :
2525 : /* Prevent cancel/die interrupt while cleaning up */
6505 tgl 2526 GIC 367 : HOLD_INTERRUPTS();
2527 :
2528 : /*
2529 : * set the current transaction state information appropriately during
2530 : * prepare processing
2531 : */
6505 tgl 2532 CBC 367 : s->state = TRANS_PREPARE;
6505 tgl 2533 EUB :
6493 tgl 2534 GIC 367 : prepared_at = GetCurrentTimestamp();
2535 :
2536 : /*
2537 : * Reserve the GID for this transaction. This could fail if the requested
2538 : * GID is invalid or already in use.
2539 : */
6504 2540 367 : gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
6504 tgl 2541 ECB : GetUserId(), MyDatabaseId);
6505 tgl 2542 GIC 356 : prepareGID = NULL;
6505 tgl 2543 ECB :
2544 : /*
2545 : * Collect data for the 2PC state file. Note that in general, no actual
2546 : * state change should happen in the called modules during this step,
2547 : * since it's still possible to fail before commit, and in that case we
2548 : * want transaction abort to be able to clean up. (In particular, the
2549 : * AtPrepare routines may error out if they find cases they cannot
2550 : * handle.) State cleanup should happen in the PostPrepare routines
6385 bruce 2551 : * below. However, some modules can go ahead and clear state here because
2552 : * they wouldn't do anything with it during abort anyway.
2553 : *
2554 : * Note: because the 2PC state file records will be replayed in the same
2555 : * order they are made, the order of these calls has to match the order in
2556 : * which we want things to happen during COMMIT PREPARED or ROLLBACK
2557 : * PREPARED; in particular, pay attention to whether things should happen
2558 : * before or after releasing the transaction's locks.
2559 : */
6505 tgl 2560 GIC 356 : StartPrepare(gxact);
2561 :
2562 356 : AtPrepare_Notify();
2563 356 : AtPrepare_Locks();
4444 heikki.linnakangas 2564 354 : AtPrepare_PredicateLocks();
5796 tgl 2565 354 : AtPrepare_PgStat();
4885 heikki.linnakangas 2566 354 : AtPrepare_MultiXact();
4809 tgl 2567 354 : AtPrepare_RelationMap();
2568 :
6505 tgl 2569 ECB : /*
2570 : * Here is where we really truly prepare.
2571 : *
6347 bruce 2572 : * We have to record transaction prepares even if we didn't make any
2573 : * updates, because the transaction manager might get confused if we lose
2574 : * a global transaction.
6505 tgl 2575 : */
6505 tgl 2576 CBC 354 : EndPrepare(gxact);
2577 :
2578 : /*
2579 : * Now we clean up backend-internal state and release internal resources.
2580 : */
2581 :
2582 : /* Reset XactLastRecEnd until the next transaction writes something */
3941 heikki.linnakangas 2583 GIC 354 : XactLastRecEnd = 0;
2584 :
533 noah 2585 ECB : /*
2586 : * Transfer our locks to a dummy PGPROC. This has to be done before
2587 : * ProcArrayClearTransaction(). Otherwise, a GetLockConflicts() would
2588 : * conclude "xact already committed or aborted" for our locks.
2589 : */
533 noah 2590 GIC 354 : PostPrepare_Locks(xid);
2591 :
6505 tgl 2592 ECB : /*
2593 : * Let others know about no transaction in progress by me. This has to be
2594 : * done *after* the prepared transaction has been marked valid, else
2595 : * someone may think it is unlocked and recyclable.
2596 : */
5692 tgl 2597 GIC 354 : ProcArrayClearTransaction(MyProc);
2598 :
6505 tgl 2599 ECB : /*
2600 : * In normal commit-processing, this is all non-critical post-transaction
2601 : * cleanup. When the transaction is prepared, however, it's important
2602 : * that the locks and other per-backend resources are transferred to the
2603 : * prepared transaction's PGPROC entry. Note that if an error is raised
2604 : * here, it's too late to abort the transaction. XXX: This probably should
2605 : * be in a critical section, to force a PANIC if any of this fails, but
3251 heikki.linnakangas 2606 : * that cure could be worse than the disease.
2607 : */
2608 :
6505 tgl 2609 GIC 354 : CallXactCallbacks(XACT_EVENT_PREPARE);
2610 :
2611 354 : ResourceOwnerRelease(TopTransactionResourceOwner,
2612 : RESOURCE_RELEASE_BEFORE_LOCKS,
2613 : true, true);
2614 :
2615 : /* Check we've released all buffer pins */
2616 354 : AtEOXact_Buffers(true);
2617 :
6453 tgl 2618 ECB : /* Clean up the relation cache */
6453 tgl 2619 GIC 354 : AtEOXact_RelationCache(true);
6453 tgl 2620 ECB :
2621 : /* notify doesn't need a postprepare call */
2622 :
5796 tgl 2623 GIC 354 : PostPrepare_PgStat();
2624 :
6505 tgl 2625 CBC 354 : PostPrepare_Inval();
2626 :
6505 tgl 2627 GIC 354 : PostPrepare_smgr();
6505 tgl 2628 ECB :
4885 heikki.linnakangas 2629 GIC 354 : PostPrepare_MultiXact(xid);
2630 :
4444 2631 354 : PostPrepare_PredicateLocks(xid);
6505 tgl 2632 ECB :
6505 tgl 2633 GIC 354 : ResourceOwnerRelease(TopTransactionResourceOwner,
6505 tgl 2634 ECB : RESOURCE_RELEASE_LOCKS,
2635 : true, true);
6505 tgl 2636 CBC 354 : ResourceOwnerRelease(TopTransactionResourceOwner,
2637 : RESOURCE_RELEASE_AFTER_LOCKS,
6505 tgl 2638 ECB : true, true);
2639 :
3251 heikki.linnakangas 2640 : /*
2641 : * Allow another backend to finish the transaction. After
2878 bruce 2642 : * PostPrepare_Twophase(), the transaction is completely detached from our
2643 : * backend. The rest is just non-critical cleanup of backend-local state.
2644 : */
3251 heikki.linnakangas 2645 CBC 354 : PostPrepare_Twophase();
2646 :
2647 : /* PREPARE acts the same as COMMIT as far as GUC is concerned */
5697 tgl 2648 GIC 354 : AtEOXact_GUC(true, 1);
6505 2649 354 : AtEOXact_SPI(true);
1643 tmunro 2650 354 : AtEOXact_Enum();
6505 tgl 2651 354 : AtEOXact_on_commit_actions(true);
2901 rhaas 2652 354 : AtEOXact_Namespace(true, false);
3826 tgl 2653 354 : AtEOXact_SMgr();
1807 tgl 2654 CBC 354 : AtEOXact_Files(true);
5903 tgl 2655 GIC 354 : AtEOXact_ComboCid();
5827 2656 354 : AtEOXact_HashTables(true);
3272 tgl 2657 ECB : /* don't call AtEOXact_PgStat here; we fixed pgstat state above */
2194 simon 2658 CBC 354 : AtEOXact_Snapshot(true, true);
2659 : /* we treat PREPARE as ROLLBACK so far as waking workers goes */
93 tgl 2660 GNC 354 : AtEOXact_ApplyLauncher(false);
2661 354 : AtEOXact_LogicalRepWorkers(false);
3272 tgl 2662 CBC 354 : pgstat_report_xact_timestamp(0);
6505 tgl 2663 ECB :
6505 tgl 2664 CBC 354 : CurrentResourceOwner = NULL;
2665 354 : ResourceOwnerDelete(TopTransactionResourceOwner);
2666 354 : s->curTransactionOwner = NULL;
2667 354 : CurTransactionResourceOwner = NULL;
2668 354 : TopTransactionResourceOwner = NULL;
2669 :
2670 354 : AtCommit_Memory();
2671 :
1473 tmunro 2672 354 : s->fullTransactionId = InvalidFullTransactionId;
6505 tgl 2673 354 : s->subTransactionId = InvalidSubTransactionId;
2674 354 : s->nestingLevel = 0;
5697 tgl 2675 GIC 354 : s->gucNestLevel = 0;
5501 tgl 2676 CBC 354 : s->childXids = NULL;
2677 354 : s->nChildXids = 0;
2678 354 : s->maxChildXids = 0;
6505 tgl 2679 ECB :
1473 tmunro 2680 CBC 354 : XactTopFullTransactionId = InvalidFullTransactionId;
2901 rhaas 2681 GIC 354 : nParallelCurrentXids = 0;
2901 rhaas 2682 ECB :
2683 : /*
6385 bruce 2684 : * done with 1st phase commit processing, set current transaction state
2685 : * back to default
6505 tgl 2686 : */
6505 tgl 2687 CBC 354 : s->state = TRANS_DEFAULT;
6505 tgl 2688 ECB :
6505 tgl 2689 CBC 354 : RESUME_INTERRUPTS();
2690 354 : }
2691 :
6505 tgl 2692 ECB :
7331 bruce 2693 : /*
2694 : * AbortTransaction
2695 : */
2696 : static void
8202 tgl 2697 GIC 20098 : AbortTransaction(void)
2698 : {
9345 bruce 2699 CBC 20098 : TransactionState s = CurrentTransactionState;
2700 : TransactionId latestXid;
2878 bruce 2701 ECB : bool is_parallel_worker;
9345 2702 :
2703 : /* Prevent cancel/die interrupt while cleaning up */
8115 tgl 2704 GIC 20098 : HOLD_INTERRUPTS();
2705 :
2706 : /* Make sure we have a valid memory context and resource owner */
5981 2707 20098 : AtAbort_Memory();
2708 20098 : AtAbort_ResourceOwner();
5981 tgl 2709 ECB :
2710 : /*
7862 2711 : * Release any LW locks we might be holding as quickly as possible.
2712 : * (Regular locks, however, must be held till we finish aborting.)
2713 : * Releasing LW locks is critical since we might try to grab them again
2714 : * while cleaning up!
2715 : */
7862 tgl 2716 CBC 20098 : LWLockReleaseAll();
2717 :
2718 : /* Clear wait information and command progress indicator */
2586 rhaas 2719 20098 : pgstat_report_wait_end();
2720 20098 : pgstat_progress_end_command();
2721 :
2722 : /* Clean up buffer context locks, too */
8147 tgl 2723 GIC 20098 : UnlockBuffers();
2724 :
2725 : /* Reset WAL record construction state */
3062 heikki.linnakangas 2726 20098 : XLogResetInsertion();
3062 heikki.linnakangas 2727 ECB :
2728 : /* Cancel condition variable sleep */
2329 rhaas 2729 GIC 20098 : ConditionVariableCancelSleep();
2329 rhaas 2730 ECB :
8120 tgl 2731 : /*
2732 : * Also clean up any open wait for lock, since the lock manager will choke
2733 : * if we try to wait for another lock before doing this.
2734 : */
4008 rhaas 2735 GIC 20098 : LockErrorCleanup();
2736 :
3418 tgl 2737 ECB : /*
2738 : * If any timeout events are still active, make sure the timeout interrupt
2739 : * is scheduled. This covers possible loss of a timeout interrupt due to
2740 : * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
2741 : * We delay this till after LockErrorCleanup so that we don't uselessly
2742 : * reschedule lock or deadlock check timeouts.
2743 : */
3418 tgl 2744 GIC 20098 : reschedule_timeouts();
2745 :
3418 tgl 2746 ECB : /*
2747 : * Re-enable signals, in case we got here by longjmp'ing out of a signal
2748 : * handler. We do this fairly early in the sequence so that the timeout
2749 : * infrastructure will be functional if needed while aborting.
2750 : */
65 tmunro 2751 GNC 20098 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
2752 :
2753 : /*
2754 : * check the current transaction state
9770 scrappy 2755 ECB : */
2901 rhaas 2756 GIC 20098 : is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
6505 tgl 2757 20098 : if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
6829 tgl 2758 UIC 0 : elog(WARNING, "AbortTransaction while in %s state",
2759 : TransStateAsString(s->state));
6856 tgl 2760 GIC 20098 : Assert(s->parent == NULL);
2761 :
8053 bruce 2762 ECB : /*
2763 : * set the current transaction state information appropriately during the
2764 : * abort processing
2765 : */
9345 bruce 2766 GIC 20098 : s->state = TRANS_ABORT;
9345 bruce 2767 ECB :
8147 tgl 2768 : /*
5575 tgl 2769 EUB : * Reset user ID which might have been changed transiently. We need this
2770 : * to clean up in case control escaped out of a SECURITY DEFINER function
5050 bruce 2771 ECB : * or other local change of CurrentUserId; therefore, the prior value of
2772 : * SecurityRestrictionContext also needs to be restored.
2773 : *
2774 : * (Note: it is not necessary to restore session authorization or role
2775 : * settings here because those can only be changed via GUC, and GUC will
2776 : * take care of rolling them back if need be.)
8147 tgl 2777 : */
4869 tgl 2778 GIC 20098 : SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
2779 :
2780 : /* Forget about any active REINDEX. */
1083 2781 20098 : ResetReindexState(s->nestingLevel);
2782 :
2783 : /* Reset logical streaming state. */
974 akapila 2784 20098 : ResetLogicalStreamingState();
2785 :
2786 : /* Reset snapshot export state. */
538 michael 2787 20098 : SnapBuildResetExportedSnapshotState();
2788 :
2901 rhaas 2789 ECB : /* If in parallel mode, clean up workers and exit parallel mode. */
2901 rhaas 2790 GIC 20098 : if (IsInParallelMode())
2791 : {
2901 rhaas 2792 CBC 3 : AtEOXact_Parallel(false);
2901 rhaas 2793 GIC 3 : s->parallelModeLevel = 0;
2794 : }
2901 rhaas 2795 ECB :
2796 : /*
2797 : * do abort processing
9770 scrappy 2798 : */
4790 bruce 2799 GIC 20098 : AfterTriggerEndXact(false); /* 'false' means it's abort */
7282 tgl 2800 20098 : AtAbort_Portals();
1100 noah 2801 CBC 20098 : smgrDoPendingSyncs(false, is_parallel_worker);
4809 tgl 2802 GIC 20098 : AtEOXact_LargeObject(false);
8951 tgl 2803 CBC 20098 : AtAbort_Notify();
1703 pg 2804 20098 : AtEOXact_RelationMap(false, is_parallel_worker);
3251 heikki.linnakangas 2805 GIC 20098 : AtAbort_Twophase();
2806 :
2807 : /*
2808 : * Advertise the fact that we aborted in pg_xact (assuming that we got as
2809 : * far as assigning an XID to advertise). But if we're inside a parallel
2901 rhaas 2810 ECB : * worker, skip this; the user backend must be the one to write the abort
2811 : * record.
6622 tgl 2812 : */
2901 rhaas 2813 CBC 20098 : if (!is_parallel_worker)
2814 20095 : latestXid = RecordTransactionAbort(false);
2901 rhaas 2815 ECB : else
2816 : {
2901 rhaas 2817 GIC 3 : latestXid = InvalidTransactionId;
2818 :
2819 : /*
2820 : * Since the parallel leader won't get our value of XactLastRecEnd in
2821 : * this case, we nudge WAL-writer ourselves in this case. See related
2822 : * comments in RecordTransactionAbort for why this matters.
2823 : */
2901 rhaas 2824 CBC 3 : XLogSetAsyncXactLSN(XactLastRecEnd);
2901 rhaas 2825 ECB : }
2826 :
2827 : TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->lxid);
5693 tgl 2828 :
2829 : /*
2830 : * Let others know about no transaction in progress by me. Note that this
2831 : * must be done _before_ releasing locks we hold and _after_
2832 : * RecordTransactionAbort.
2833 : */
5692 tgl 2834 GIC 20098 : ProcArrayEndTransaction(MyProc, latestXid);
7961 JanWieck 2835 ECB :
2836 : /*
2837 : * Post-abort cleanup. See notes in CommitTransaction() concerning
2838 : * ordering. We can skip all of it if the transaction failed before
2839 : * creating a resource owner.
2840 : */
4823 tgl 2841 GIC 20098 : if (TopTransactionResourceOwner != NULL)
2842 : {
2901 rhaas 2843 20098 : if (is_parallel_worker)
2844 3 : CallXactCallbacks(XACT_EVENT_PARALLEL_ABORT);
2901 rhaas 2845 ECB : else
2901 rhaas 2846 GIC 20095 : CallXactCallbacks(XACT_EVENT_ABORT);
2847 :
4823 tgl 2848 20098 : ResourceOwnerRelease(TopTransactionResourceOwner,
2849 : RESOURCE_RELEASE_BEFORE_LOCKS,
2850 : false, true);
2851 20098 : AtEOXact_Buffers(false);
4823 tgl 2852 CBC 20098 : AtEOXact_RelationCache(false);
4823 tgl 2853 GIC 20098 : AtEOXact_Inval(false);
4823 tgl 2854 CBC 20098 : AtEOXact_MultiXact();
2855 20098 : ResourceOwnerRelease(TopTransactionResourceOwner,
2856 : RESOURCE_RELEASE_LOCKS,
4823 tgl 2857 ECB : false, true);
4823 tgl 2858 GIC 20098 : ResourceOwnerRelease(TopTransactionResourceOwner,
4823 tgl 2859 ECB : RESOURCE_RELEASE_AFTER_LOCKS,
2860 : false, true);
3951 rhaas 2861 GIC 20098 : smgrDoPendingDeletes(false);
4823 tgl 2862 ECB :
4823 tgl 2863 CBC 20098 : AtEOXact_GUC(false, 1);
2864 20098 : AtEOXact_SPI(false);
1643 tmunro 2865 20098 : AtEOXact_Enum();
4823 tgl 2866 20098 : AtEOXact_on_commit_actions(false);
2901 rhaas 2867 GIC 20098 : AtEOXact_Namespace(false, is_parallel_worker);
3826 tgl 2868 20098 : AtEOXact_SMgr();
1807 tgl 2869 CBC 20098 : AtEOXact_Files(false);
4823 tgl 2870 GIC 20098 : AtEOXact_ComboCid();
2871 20098 : AtEOXact_HashTables(false);
1460 akapila 2872 CBC 20098 : AtEOXact_PgStat(false, is_parallel_worker);
2169 peter_e 2873 GIC 20098 : AtEOXact_ApplyLauncher(false);
93 tgl 2874 GNC 20098 : AtEOXact_LogicalRepWorkers(false);
4823 tgl 2875 CBC 20098 : pgstat_report_xact_timestamp(0);
4823 tgl 2876 ECB : }
7937 2877 :
8053 bruce 2878 : /*
2879 : * State remains TRANS_ABORT until CleanupTransaction().
8320 tgl 2880 : */
8115 tgl 2881 CBC 20098 : RESUME_INTERRUPTS();
8320 2882 20098 : }
8320 tgl 2883 ECB :
7331 bruce 2884 : /*
7452 2885 : * CleanupTransaction
8320 tgl 2886 : */
2887 : static void
8202 tgl 2888 GIC 20098 : CleanupTransaction(void)
2889 : {
8320 2890 20098 : TransactionState s = CurrentTransactionState;
2891 :
2892 : /*
8053 bruce 2893 ECB : * State should still be TRANS_ABORT from AbortTransaction().
8320 tgl 2894 : */
8320 tgl 2895 GIC 20098 : if (s->state != TRANS_ABORT)
6826 tgl 2896 UIC 0 : elog(FATAL, "CleanupTransaction: unexpected state %s",
2897 : TransStateAsString(s->state));
2898 :
2899 : /*
8053 bruce 2900 ECB : * do abort cleanup processing
2901 : */
7282 tgl 2902 CBC 20098 : AtCleanup_Portals(); /* now safe to release portal memory */
2118 tgl 2903 GIC 20098 : AtEOXact_Snapshot(false, true); /* and release the transaction's snapshots */
2904 :
6797 bruce 2905 20098 : CurrentResourceOwner = NULL; /* and resource owner */
6779 tgl 2906 20098 : if (TopTransactionResourceOwner)
6779 tgl 2907 CBC 20098 : ResourceOwnerDelete(TopTransactionResourceOwner);
6840 tgl 2908 GBC 20098 : s->curTransactionOwner = NULL;
6840 tgl 2909 GIC 20098 : CurTransactionResourceOwner = NULL;
2910 20098 : TopTransactionResourceOwner = NULL;
2911 :
7282 2912 20098 : AtCleanup_Memory(); /* and transaction memory */
2913 :
1473 tmunro 2914 CBC 20098 : s->fullTransactionId = InvalidFullTransactionId;
6779 tgl 2915 20098 : s->subTransactionId = InvalidSubTransactionId;
6856 tgl 2916 GIC 20098 : s->nestingLevel = 0;
5697 tgl 2917 CBC 20098 : s->gucNestLevel = 0;
5501 2918 20098 : s->childXids = NULL;
2919 20098 : s->nChildXids = 0;
2920 20098 : s->maxChildXids = 0;
2901 rhaas 2921 20098 : s->parallelModeLevel = 0;
2901 rhaas 2922 ECB :
1473 tmunro 2923 GIC 20098 : XactTopFullTransactionId = InvalidFullTransactionId;
2901 rhaas 2924 CBC 20098 : nParallelCurrentXids = 0;
2925 :
8053 bruce 2926 ECB : /*
2927 : * done with abort processing, set current transaction state back to
2928 : * default
9770 scrappy 2929 : */
9345 bruce 2930 CBC 20098 : s->state = TRANS_DEFAULT;
2931 20098 : }
9345 bruce 2932 ECB :
7331 2933 : /*
2934 : * StartTransactionCommand
9345 2935 : */
2936 : void
7270 tgl 2937 GIC 548107 : StartTransactionCommand(void)
2938 : {
9345 bruce 2939 548107 : TransactionState s = CurrentTransactionState;
2940 :
2941 548107 : switch (s->blockState)
9345 bruce 2942 ECB : {
8053 2943 : /*
2944 : * if we aren't in a transaction block, we just do our usual start
2945 : * transaction.
2946 : */
9344 bruce 2947 GIC 484070 : case TBLOCK_DEFAULT:
2948 484070 : StartTransaction();
6943 bruce 2949 CBC 484070 : s->blockState = TBLOCK_STARTED;
6943 bruce 2950 GIC 484070 : break;
6943 bruce 2951 ECB :
2952 : /*
6385 2953 : * We are somewhere in a transaction block or subtransaction and
2954 : * about to start a new command. For now we do nothing, but
2955 : * someday we may do command-local resource initialization. (Note
2956 : * that any needed CommandCounterIncrement was done by the
2957 : * previous CommitTransactionCommand.)
2958 : */
9344 bruce 2959 CBC 63238 : case TBLOCK_INPROGRESS:
2040 tgl 2960 ECB : case TBLOCK_IMPLICIT_INPROGRESS:
6856 2961 : case TBLOCK_SUBINPROGRESS:
9344 bruce 2962 CBC 63238 : break;
2963 :
2964 : /*
2965 : * Here we are in a failed transaction block (one of the commands
2966 : * caused an abort) so we do nothing but remain in the abort
2967 : * state. Eventually we will get a ROLLBACK command which will
2968 : * get us out of this state. (It is up to other code to ensure
2969 : * that no commands other than ROLLBACK will be processed in these
2970 : * states.)
9344 bruce 2971 ECB : */
9344 bruce 2972 GIC 799 : case TBLOCK_ABORT:
2973 : case TBLOCK_SUBABORT:
9344 bruce 2974 CBC 799 : break;
2975 :
2976 : /* These cases are invalid. */
6856 tgl 2977 UIC 0 : case TBLOCK_STARTED:
2978 : case TBLOCK_BEGIN:
2979 : case TBLOCK_PARALLEL_INPROGRESS:
2980 : case TBLOCK_SUBBEGIN:
2981 : case TBLOCK_END:
2982 : case TBLOCK_SUBRELEASE:
2983 : case TBLOCK_SUBCOMMIT:
6779 tgl 2984 ECB : case TBLOCK_ABORT_END:
2985 : case TBLOCK_SUBABORT_END:
2986 : case TBLOCK_ABORT_PENDING:
2987 : case TBLOCK_SUBABORT_PENDING:
2988 : case TBLOCK_SUBRESTART:
6779 tgl 2989 EUB : case TBLOCK_SUBABORT_RESTART:
2990 : case TBLOCK_PREPARE:
6779 tgl 2991 UIC 0 : elog(ERROR, "StartTransactionCommand: unexpected state %s",
2992 : BlockStateAsString(s->blockState));
2993 : break;
2994 : }
2995 :
2996 : /*
2997 : * We must switch to CurTransactionContext before returning. This is
2998 : * already done if we called StartTransaction, otherwise not.
2999 : */
6856 tgl 3000 GIC 548107 : Assert(CurTransactionContext != NULL);
3001 548107 : MemoryContextSwitchTo(CurTransactionContext);
9345 bruce 3002 548107 : }
9345 bruce 3003 EUB :
3004 :
3005 : /*
3006 : * Simple system for saving and restoring transaction characteristics
3007 : * (isolation level, read only, deferrable). We need this for transaction
3008 : * chaining, so that we can set the characteristics of the new transaction to
3009 : * be the same as the previous one. (We need something like this because the
3010 : * GUC system resets the characteristics at transaction end, so for example
3011 : * just skipping the reset in StartTransaction() won't work.)
1477 peter 3012 ECB : */
3013 : void
405 tgl 3014 CBC 529446 : SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)
3015 : {
405 tgl 3016 GIC 529446 : s->save_XactIsoLevel = XactIsoLevel;
3017 529446 : s->save_XactReadOnly = XactReadOnly;
3018 529446 : s->save_XactDeferrable = XactDeferrable;
1477 peter 3019 529446 : }
3020 :
3021 : void
405 tgl 3022 31 : RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
3023 : {
3024 31 : XactIsoLevel = s->save_XactIsoLevel;
3025 31 : XactReadOnly = s->save_XactReadOnly;
405 tgl 3026 CBC 31 : XactDeferrable = s->save_XactDeferrable;
1477 peter 3027 GIC 31 : }
1477 peter 3028 ECB :
3029 :
7331 bruce 3030 : /*
7452 3031 : * CommitTransactionCommand
3032 : */
3033 : void
7270 tgl 3034 CBC 529442 : CommitTransactionCommand(void)
3035 : {
9345 bruce 3036 529442 : TransactionState s = CurrentTransactionState;
405 tgl 3037 ECB : SavedTransactionCharacteristics savetc;
9345 bruce 3038 :
405 tgl 3039 CBC 529442 : SaveTransactionCharacteristics(&savetc);
3040 :
9345 bruce 3041 GIC 529442 : switch (s->blockState)
3042 : {
3043 : /*
3044 : * These shouldn't happen. TBLOCK_DEFAULT means the previous
3045 : * StartTransactionCommand didn't set the STARTED state
2901 rhaas 3046 ECB : * appropriately, while TBLOCK_PARALLEL_INPROGRESS should be ended
3047 : * by EndParallelWorkerTransaction(), not this function.
6943 bruce 3048 : */
6943 bruce 3049 UIC 0 : case TBLOCK_DEFAULT:
3050 : case TBLOCK_PARALLEL_INPROGRESS:
6830 tgl 3051 LBC 0 : elog(FATAL, "CommitTransactionCommand: unexpected state %s",
3052 : BlockStateAsString(s->blockState));
6943 bruce 3053 ECB : break;
3054 :
3055 : /*
3056 : * If we aren't in a transaction block, just do our usual
3057 : * transaction commit, and return to the idle state.
3058 : */
6943 bruce 3059 GIC 458478 : case TBLOCK_STARTED:
7270 tgl 3060 458478 : CommitTransaction();
6943 bruce 3061 GBC 458468 : s->blockState = TBLOCK_DEFAULT;
9344 bruce 3062 GIC 458468 : break;
9344 bruce 3063 EUB :
3064 : /*
3065 : * We are completing a "BEGIN TRANSACTION" command, so we change
3066 : * to the "transaction block in progress" state and return. (We
3067 : * assume the BEGIN did nothing to the database, so we need no
3068 : * CommandCounterIncrement.)
3069 : */
9344 bruce 3070 GIC 7436 : case TBLOCK_BEGIN:
9344 bruce 3071 CBC 7436 : s->blockState = TBLOCK_INPROGRESS;
3072 7436 : break;
9344 bruce 3073 ECB :
8053 3074 : /*
3075 : * This is the case when we have finished executing a command
3076 : * someplace within a transaction block. We increment the command
3077 : * counter and return.
3078 : */
9344 bruce 3079 GIC 47103 : case TBLOCK_INPROGRESS:
3080 : case TBLOCK_IMPLICIT_INPROGRESS:
3081 : case TBLOCK_SUBINPROGRESS:
9344 bruce 3082 CBC 47103 : CommandCounterIncrement();
3083 47103 : break;
9344 bruce 3084 ECB :
3085 : /*
3086 : * We are completing a "COMMIT" command. Do it and return to the
3087 : * idle state.
3088 : */
9344 bruce 3089 GIC 5027 : case TBLOCK_END:
3090 5027 : CommitTransaction();
8320 tgl 3091 CBC 4836 : s->blockState = TBLOCK_DEFAULT;
1477 peter 3092 GIC 4836 : if (s->chain)
3093 : {
1477 peter 3094 CBC 6 : StartTransaction();
3095 6 : s->blockState = TBLOCK_INPROGRESS;
1477 peter 3096 GIC 6 : s->chain = false;
405 tgl 3097 6 : RestoreTransactionCharacteristics(&savetc);
3098 : }
9344 bruce 3099 4836 : break;
3100 :
8053 bruce 3101 ECB : /*
6385 3102 : * Here we are in the middle of a transaction block but one of the
3103 : * commands caused an abort so we do nothing but remain in the
2884 magnus 3104 : * abort state. Eventually we will get a ROLLBACK command.
3105 : */
9344 bruce 3106 LBC 0 : case TBLOCK_ABORT:
6779 tgl 3107 ECB : case TBLOCK_SUBABORT:
9344 bruce 3108 LBC 0 : break;
9344 bruce 3109 ECB :
3110 : /*
6385 3111 : * Here we were in an aborted transaction block and we just got
3112 : * the ROLLBACK command from the user, so clean up the
3113 : * already-aborted transaction and return to the idle state.
3114 : */
6779 tgl 3115 GIC 612 : case TBLOCK_ABORT_END:
8320 3116 612 : CleanupTransaction();
9344 bruce 3117 612 : s->blockState = TBLOCK_DEFAULT;
1477 peter 3118 GBC 612 : if (s->chain)
3119 : {
3120 6 : StartTransaction();
1477 peter 3121 GIC 6 : s->blockState = TBLOCK_INPROGRESS;
3122 6 : s->chain = false;
405 tgl 3123 6 : RestoreTransactionCharacteristics(&savetc);
3124 : }
9344 bruce 3125 612 : break;
3126 :
6856 tgl 3127 ECB : /*
6385 bruce 3128 : * Here we were in a perfectly good transaction block but the user
3260 3129 : * told us to ROLLBACK anyway. We have to abort the transaction
6385 3130 : * and then clean up.
3131 : */
6779 tgl 3132 CBC 901 : case TBLOCK_ABORT_PENDING:
3133 901 : AbortTransaction();
3134 901 : CleanupTransaction();
3135 901 : s->blockState = TBLOCK_DEFAULT;
1477 peter 3136 GIC 901 : if (s->chain)
1477 peter 3137 ECB : {
1477 peter 3138 GIC 9 : StartTransaction();
3139 9 : s->blockState = TBLOCK_INPROGRESS;
3140 9 : s->chain = false;
405 tgl 3141 9 : RestoreTransactionCharacteristics(&savetc);
3142 : }
6830 3143 901 : break;
6830 tgl 3144 ECB :
6505 3145 : /*
3146 : * We are completing a "PREPARE TRANSACTION" command. Do it and
3147 : * return to the idle state.
3148 : */
6505 tgl 3149 GIC 256 : case TBLOCK_PREPARE:
6505 tgl 3150 CBC 256 : PrepareTransaction();
3151 209 : s->blockState = TBLOCK_DEFAULT;
3152 209 : break;
6505 tgl 3153 ECB :
3154 : /*
3155 : * The user issued a SAVEPOINT inside a transaction block.
3156 : * Start a subtransaction. (DefineSavepoint already did
3157 : * PushTransaction, so as to have someplace to put the SUBBEGIN
3158 : * state.)
3159 : */
6856 tgl 3160 GIC 8435 : case TBLOCK_SUBBEGIN:
6856 tgl 3161 CBC 8435 : StartSubTransaction();
3162 8435 : s->blockState = TBLOCK_SUBINPROGRESS;
3163 8435 : break;
9345 bruce 3164 ECB :
3165 : /*
3166 : * The user issued a RELEASE command, so we end the current
3167 : * subtransaction and return to the parent transaction. The parent
3168 : * might be ended too, so repeat till we find an INPROGRESS
3169 : * transaction or subtransaction.
3170 : */
4282 simon 3171 GIC 221 : case TBLOCK_SUBRELEASE:
6797 bruce 3172 ECB : do
3173 : {
4232 simon 3174 CBC 221 : CommitSubTransaction();
6797 bruce 3175 221 : s = CurrentTransactionState; /* changed by pop */
4282 simon 3176 GIC 221 : } while (s->blockState == TBLOCK_SUBRELEASE);
3177 :
3178 135 : Assert(s->blockState == TBLOCK_INPROGRESS ||
3179 : s->blockState == TBLOCK_SUBINPROGRESS);
3180 135 : break;
3181 :
3182 : /*
3183 : * The user issued a COMMIT, so we end the current subtransaction
3184 : * hierarchy and perform final commit. We do this by rolling up
3185 : * any subtransactions into their parent, which leads to O(N^2)
4232 simon 3186 ECB : * operations with respect to resource owners - this isn't that
3955 bruce 3187 : * bad until we approach a thousands of savepoints but is
3188 : * necessary for correctness should after triggers create new
3189 : * resource owners.
4282 simon 3190 : */
4282 simon 3191 GIC 570 : case TBLOCK_SUBCOMMIT:
4282 simon 3192 ECB : do
3193 : {
4232 simon 3194 GIC 570 : CommitSubTransaction();
4282 3195 570 : s = CurrentTransactionState; /* changed by pop */
3196 570 : } while (s->blockState == TBLOCK_SUBCOMMIT);
3197 : /* If we had a COMMIT command, finish off the main xact too */
6785 tgl 3198 503 : if (s->blockState == TBLOCK_END)
3199 : {
3200 357 : Assert(s->parent == NULL);
3201 357 : CommitTransaction();
3202 344 : s->blockState = TBLOCK_DEFAULT;
779 fujii 3203 CBC 344 : if (s->chain)
3204 : {
779 fujii 3205 GIC 6 : StartTransaction();
779 fujii 3206 CBC 6 : s->blockState = TBLOCK_INPROGRESS;
3207 6 : s->chain = false;
405 tgl 3208 6 : RestoreTransactionCharacteristics(&savetc);
3209 : }
6785 tgl 3210 ECB : }
6505 tgl 3211 GIC 146 : else if (s->blockState == TBLOCK_PREPARE)
6505 tgl 3212 ECB : {
6505 tgl 3213 CBC 146 : Assert(s->parent == NULL);
3214 146 : PrepareTransaction();
3215 145 : s->blockState = TBLOCK_DEFAULT;
3216 : }
6779 tgl 3217 ECB : else
4282 simon 3218 LBC 0 : elog(ERROR, "CommitTransactionCommand: unexpected state %s",
4282 simon 3219 ECB : BlockStateAsString(s->blockState));
6856 tgl 3220 CBC 489 : break;
3221 :
3222 : /*
6779 tgl 3223 ECB : * The current already-failed subtransaction is ending due to a
3224 : * ROLLBACK or ROLLBACK TO command, so pop it and recursively
3225 : * examine the parent (which could be in any of several states).
6856 3226 : */
6779 tgl 3227 CBC 40 : case TBLOCK_SUBABORT_END:
6779 tgl 3228 GIC 40 : CleanupSubTransaction();
3229 40 : CommitTransactionCommand();
6856 tgl 3230 GBC 40 : break;
3231 :
6856 tgl 3232 ECB : /*
3233 : * As above, but it's not dead yet, so abort first.
3234 : */
6779 tgl 3235 GIC 168 : case TBLOCK_SUBABORT_PENDING:
3236 168 : AbortSubTransaction();
3237 168 : CleanupSubTransaction();
3238 168 : CommitTransactionCommand();
6856 tgl 3239 CBC 168 : break;
6856 tgl 3240 ECB :
3241 : /*
6779 3242 : * The current subtransaction is the target of a ROLLBACK TO
3243 : * command. Abort and pop it, then start a new subtransaction
3244 : * with the same name.
3245 : */
6779 tgl 3246 GIC 252 : case TBLOCK_SUBRESTART:
6830 tgl 3247 ECB : {
6779 3248 : char *name;
3249 : int savepointLevel;
3250 :
3251 : /* save name and keep Cleanup from freeing it */
6779 tgl 3252 GIC 252 : name = s->name;
3253 252 : s->name = NULL;
3254 252 : savepointLevel = s->savepointLevel;
3255 :
3256 252 : AbortSubTransaction();
3257 252 : CleanupSubTransaction();
6830 tgl 3258 ECB :
6779 tgl 3259 GIC 252 : DefineSavepoint(NULL);
3260 252 : s = CurrentTransactionState; /* changed by push */
3261 252 : s->name = name;
3262 252 : s->savepointLevel = savepointLevel;
3263 :
6830 tgl 3264 ECB : /* This is the same as TBLOCK_SUBBEGIN case */
163 peter 3265 GNC 252 : Assert(s->blockState == TBLOCK_SUBBEGIN);
6830 tgl 3266 CBC 252 : StartSubTransaction();
6830 tgl 3267 GIC 252 : s->blockState = TBLOCK_SUBINPROGRESS;
6830 tgl 3268 ECB : }
6856 tgl 3269 CBC 252 : break;
3270 :
6779 tgl 3271 ECB : /*
6385 bruce 3272 : * Same as above, but the subtransaction had already failed, so we
3273 : * don't need AbortSubTransaction.
6779 tgl 3274 : */
6779 tgl 3275 GIC 96 : case TBLOCK_SUBABORT_RESTART:
3276 : {
6779 tgl 3277 ECB : char *name;
3278 : int savepointLevel;
6797 bruce 3279 :
3280 : /* save name and keep Cleanup from freeing it */
6779 tgl 3281 CBC 96 : name = s->name;
6779 tgl 3282 GIC 96 : s->name = NULL;
3283 96 : savepointLevel = s->savepointLevel;
3284 :
3285 96 : CleanupSubTransaction();
3286 :
6779 tgl 3287 CBC 96 : DefineSavepoint(NULL);
6779 tgl 3288 GIC 96 : s = CurrentTransactionState; /* changed by push */
3289 96 : s->name = name;
3290 96 : s->savepointLevel = savepointLevel;
3291 :
3292 : /* This is the same as TBLOCK_SUBBEGIN case */
163 peter 3293 GNC 96 : Assert(s->blockState == TBLOCK_SUBBEGIN);
6779 tgl 3294 CBC 96 : StartSubTransaction();
3295 96 : s->blockState = TBLOCK_SUBINPROGRESS;
3296 : }
3297 96 : break;
3298 : }
6830 3299 529180 : }
6830 tgl 3300 ECB :
6856 3301 : /*
3302 : * AbortCurrentTransaction
3303 : */
3304 : void
6856 tgl 3305 CBC 19890 : AbortCurrentTransaction(void)
6856 tgl 3306 ECB : {
6856 tgl 3307 CBC 19890 : TransactionState s = CurrentTransactionState;
3308 :
3309 19890 : switch (s->blockState)
3310 : {
6943 bruce 3311 43 : case TBLOCK_DEFAULT:
6622 tgl 3312 GIC 43 : if (s->state == TRANS_DEFAULT)
3313 : {
3314 : /* we are idle, so nothing to do */
3315 : }
3316 : else
6622 tgl 3317 ECB : {
3318 : /*
3319 : * We can get here after an error during transaction start
3320 : * (state will be TRANS_START). Need to clean up the
3321 : * incompletely started transaction. First, adjust the
3322 : * low-level state to suppress warning message from
3323 : * AbortTransaction.
3324 : */
6622 tgl 3325 UIC 0 : if (s->state == TRANS_START)
3326 0 : s->state = TRANS_INPROGRESS;
3327 0 : AbortTransaction();
3328 0 : CleanupTransaction();
3329 : }
6943 bruce 3330 GIC 43 : break;
3331 :
3332 : /*
3333 : * If we aren't in a transaction block, we just do the basic abort
3334 : * & cleanup transaction. For this purpose, we treat an implicit
3335 : * transaction block as if it were a simple statement.
3336 : */
6943 bruce 3337 GBC 17967 : case TBLOCK_STARTED:
2040 tgl 3338 EUB : case TBLOCK_IMPLICIT_INPROGRESS:
9344 bruce 3339 GBC 17967 : AbortTransaction();
7270 tgl 3340 17967 : CleanupTransaction();
6943 bruce 3341 GIC 17967 : s->blockState = TBLOCK_DEFAULT;
9344 bruce 3342 CBC 17967 : break;
3343 :
3344 : /*
3345 : * If we are in TBLOCK_BEGIN it means something screwed up right
3346 : * after reading "BEGIN TRANSACTION". We assume that the user
3347 : * will interpret the error as meaning the BEGIN failed to get him
3348 : * into a transaction block, so we should abort and return to idle
6385 bruce 3349 ECB : * state.
3350 : */
9344 bruce 3351 LBC 0 : case TBLOCK_BEGIN:
3352 0 : AbortTransaction();
6779 tgl 3353 0 : CleanupTransaction();
3354 0 : s->blockState = TBLOCK_DEFAULT;
9344 bruce 3355 UIC 0 : break;
3356 :
3357 : /*
3358 : * We are somewhere in a transaction block and we've gotten a
3359 : * failure, so we abort the transaction and set up the persistent
3360 : * ABORT state. We will stay in ABORT until we get a ROLLBACK.
3361 : */
9344 bruce 3362 GIC 622 : case TBLOCK_INPROGRESS:
2901 rhaas 3363 EUB : case TBLOCK_PARALLEL_INPROGRESS:
9344 bruce 3364 GBC 622 : AbortTransaction();
6943 3365 622 : s->blockState = TBLOCK_ABORT;
6779 tgl 3366 EUB : /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
9344 bruce 3367 GBC 622 : break;
3368 :
3369 : /*
3370 : * Here, we failed while trying to COMMIT. Clean up the
3371 : * transaction and return to idle state (we do not want to stay in
3372 : * the transaction).
3373 : */
9344 bruce 3374 CBC 204 : case TBLOCK_END:
9344 bruce 3375 GIC 204 : AbortTransaction();
8320 tgl 3376 CBC 204 : CleanupTransaction();
6943 bruce 3377 204 : s->blockState = TBLOCK_DEFAULT;
9344 bruce 3378 GIC 204 : break;
9344 bruce 3379 ECB :
3380 : /*
3381 : * Here, we are already in an aborted transaction state and are
3382 : * waiting for a ROLLBACK, but for some reason we failed again! So
3383 : * we just remain in the abort state.
3384 : */
9344 bruce 3385 GIC 52 : case TBLOCK_ABORT:
6856 tgl 3386 ECB : case TBLOCK_SUBABORT:
9344 bruce 3387 CBC 52 : break;
9344 bruce 3388 ECB :
8053 3389 : /*
6779 tgl 3390 : * We are in a failed transaction and we got the ROLLBACK command.
3391 : * We have already aborted, we just need to cleanup and go to idle
3392 : * state.
3393 : */
6779 tgl 3394 UIC 0 : case TBLOCK_ABORT_END:
8320 3395 0 : CleanupTransaction();
9344 bruce 3396 0 : s->blockState = TBLOCK_DEFAULT;
9344 bruce 3397 LBC 0 : break;
3398 :
6856 tgl 3399 ECB : /*
3400 : * We are in a live transaction and we got a ROLLBACK command.
3401 : * Abort, cleanup, go to idle state.
3402 : */
6779 tgl 3403 UIC 0 : case TBLOCK_ABORT_PENDING:
3404 0 : AbortTransaction();
3405 0 : CleanupTransaction();
6779 tgl 3406 UBC 0 : s->blockState = TBLOCK_DEFAULT;
6856 3407 0 : break;
6856 tgl 3408 EUB :
6505 3409 : /*
3410 : * Here, we failed while trying to PREPARE. Clean up the
3411 : * transaction and return to idle state (we do not want to stay in
3412 : * the transaction).
3413 : */
6505 tgl 3414 GIC 48 : case TBLOCK_PREPARE:
6505 tgl 3415 GBC 48 : AbortTransaction();
3416 48 : CleanupTransaction();
3417 48 : s->blockState = TBLOCK_DEFAULT;
3418 48 : break;
6505 tgl 3419 EUB :
3420 : /*
3421 : * We got an error inside a subtransaction. Abort just the
3422 : * subtransaction, and go to the persistent SUBABORT state until
3423 : * we get ROLLBACK.
3424 : */
6856 tgl 3425 GIC 954 : case TBLOCK_SUBINPROGRESS:
6856 tgl 3426 CBC 954 : AbortSubTransaction();
3427 954 : s->blockState = TBLOCK_SUBABORT;
3428 954 : break;
6856 tgl 3429 ECB :
3430 : /*
3431 : * If we failed while trying to create a subtransaction, clean up
3432 : * the broken subtransaction and abort the parent. The same
3433 : * applies if we get a failure while ending a subtransaction.
3434 : */
6779 tgl 3435 UIC 0 : case TBLOCK_SUBBEGIN:
3436 : case TBLOCK_SUBRELEASE:
4282 simon 3437 ECB : case TBLOCK_SUBCOMMIT:
6830 tgl 3438 : case TBLOCK_SUBABORT_PENDING:
6779 3439 : case TBLOCK_SUBRESTART:
6856 tgl 3440 LBC 0 : AbortSubTransaction();
6856 tgl 3441 UIC 0 : CleanupSubTransaction();
3442 0 : AbortCurrentTransaction();
3443 0 : break;
3444 :
3445 : /*
3446 : * Same as above, except the Abort() was already done.
6856 tgl 3447 EUB : */
6779 tgl 3448 UIC 0 : case TBLOCK_SUBABORT_END:
3449 : case TBLOCK_SUBABORT_RESTART:
6856 3450 0 : CleanupSubTransaction();
3451 0 : AbortCurrentTransaction();
6856 tgl 3452 UBC 0 : break;
9345 bruce 3453 EUB : }
9345 bruce 3454 GBC 19890 : }
9345 bruce 3455 EUB :
3456 : /*
3457 : * PreventInTransactionBlock
3458 : *
3459 : * This routine is to be called by statements that must not run inside
7452 3460 : * a transaction block, typically because they have non-rollback-able
3461 : * side effects or do internal commits.
7475 tgl 3462 : *
151 3463 : * If this routine completes successfully, then the calling statement is
3464 : * guaranteed that if it completes without error, its results will be
3465 : * committed immediately.
151 tgl 3466 ECB : *
3467 : * If we have already started a transaction block, issue an error; also issue
3468 : * an error if we appear to be running inside a user-defined function (which
3469 : * could issue more commands and possibly cause a failure after the statement
3470 : * completes). Subtransactions are verboten too.
3471 : *
3472 : * We must also set XACT_FLAGS_NEEDIMMEDIATECOMMIT in MyXactFlags, to ensure
3473 : * that postgres.c follows through by committing after the statement is done.
3474 : *
3475 : * isTopLevel: passed down from ProcessUtility to determine whether we are
3476 : * inside a function. (We will always fail if this is false, but it's
3477 : * convenient to centralize the check here instead of making callers do it.)
3478 : * stmtType: statement type name, for error messages.
3479 : */
3480 : void
1878 peter_e 3481 GIC 5265 : PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
3482 : {
3483 : /*
3484 : * xact block already started?
3485 : */
7475 tgl 3486 5265 : if (IsTransactionBlock())
7202 3487 48 : ereport(ERROR,
3488 : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
3489 : /* translator: %s represents an SQL statement name */
3490 : errmsg("%s cannot run inside a transaction block",
3491 : stmtType)));
3492 :
6856 tgl 3493 ECB : /*
3494 : * subtransaction?
3495 : */
6856 tgl 3496 GIC 5217 : if (IsSubTransaction())
6856 tgl 3497 UIC 0 : ereport(ERROR,
6856 tgl 3498 ECB : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
3499 : /* translator: %s represents an SQL statement name */
3500 : errmsg("%s cannot run inside a subtransaction",
3501 : stmtType)));
3502 :
3503 : /*
3504 : * inside a pipeline that has started an implicit transaction?
3505 : */
117 tgl 3506 GIC 5217 : if (MyXactFlags & XACT_FLAGS_PIPELINING)
117 tgl 3507 UIC 0 : ereport(ERROR,
117 tgl 3508 ECB : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
117 tgl 3509 EUB : /* translator: %s represents an SQL statement name */
3510 : errmsg("%s cannot be executed within a pipeline",
3511 : stmtType)));
3512 :
3513 : /*
3514 : * inside a function call?
3515 : */
5871 tgl 3516 GIC 5217 : if (!isTopLevel)
7202 3517 3 : ereport(ERROR,
7202 tgl 3518 ECB : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
7188 bruce 3519 EUB : /* translator: %s represents an SQL statement name */
3520 : errmsg("%s cannot be executed from a function", stmtType)));
3521 :
3522 : /* If we got past IsTransactionBlock test, should be in default state */
6943 bruce 3523 GIC 5214 : if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
6896 tgl 3524 4571 : CurrentTransactionState->blockState != TBLOCK_STARTED)
6856 tgl 3525 UIC 0 : elog(FATAL, "cannot prevent transaction chain");
3526 :
3527 : /* All okay. Set the flag to make sure the right thing happens later. */
257 tgl 3528 CBC 5214 : MyXactFlags |= XACT_FLAGS_NEEDIMMEDIATECOMMIT;
7475 3529 5214 : }
3530 :
3531 : /*
3532 : * WarnNoTransactionBlock
3533 : * RequireTransactionBlock
3534 : *
1878 peter_e 3535 ECB : * These two functions allow for warnings or errors if a command is executed
3536 : * outside of a transaction block. This is useful for commands that have no
1878 peter_e 3537 EUB : * effects that persist past transaction end (and so calling them outside a
3538 : * transaction block is presumably an error). DECLARE CURSOR is an example.
3539 : * While top-level transaction control commands (BEGIN/COMMIT/ABORT) and SET
1878 peter_e 3540 ECB : * that have no effect issue warnings, all other no-effect commands generate
3541 : * errors.
3542 : *
3543 : * If we appear to be running inside a user-defined function, we do not
3544 : * issue anything, since the function could issue more commands that make
3545 : * use of the current statement's results. Likewise subtransactions.
3546 : * Thus these are inverses for PreventInTransactionBlock.
3547 : *
3548 : * isTopLevel: passed down from ProcessUtility to determine whether we are
3549 : * inside a function.
3550 : * stmtType: statement type name, for warning or error messages.
3551 : */
3552 : void
1878 peter_e 3553 GIC 779 : WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
3554 : {
3555 779 : CheckTransactionBlock(isTopLevel, false, stmtType);
3422 bruce 3556 779 : }
3557 :
3558 : void
1878 peter_e 3559 3296 : RequireTransactionBlock(bool isTopLevel, const char *stmtType)
3560 : {
3561 3296 : CheckTransactionBlock(isTopLevel, true, stmtType);
3422 bruce 3562 3286 : }
3563 :
3564 : /*
1878 peter_e 3565 ECB : * This is the implementation of the above two.
3566 : */
3422 bruce 3567 : static void
1878 peter_e 3568 CBC 4075 : CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
3569 : {
3570 : /*
7447 tgl 3571 ECB : * xact block already started?
3572 : */
7447 tgl 3573 CBC 4075 : if (IsTransactionBlock())
3574 4046 : return;
3575 :
3576 : /*
3577 : * subtransaction?
3578 : */
6856 tgl 3579 GIC 29 : if (IsSubTransaction())
6856 tgl 3580 LBC 0 : return;
3581 :
3582 : /*
3583 : * inside a function call?
3584 : */
5871 tgl 3585 CBC 29 : if (!isTopLevel)
7447 3586 13 : return;
3587 :
3422 bruce 3588 GIC 16 : ereport(throwError ? ERROR : WARNING,
3589 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3590 : /* translator: %s represents an SQL statement name */
5911 bruce 3591 ECB : errmsg("%s can only be used in transaction blocks",
7202 tgl 3592 EUB : stmtType)));
3593 : }
3594 :
3595 : /*
3596 : * IsInTransactionBlock
6896 tgl 3597 ECB : *
3598 : * This routine is for statements that need to behave differently inside
3599 : * a transaction block than when running as single commands. ANALYZE is
3600 : * currently the only example.
3601 : *
3602 : * If this routine returns "false", then the calling statement is allowed
3603 : * to perform internal transaction-commit-and-start cycles; there is not a
3604 : * risk of messing up any transaction already in progress. (Note that this
3605 : * is not the identical guarantee provided by PreventInTransactionBlock,
3606 : * since we will not force a post-statement commit.)
3607 : *
3608 : * isTopLevel: passed down from ProcessUtility to determine whether we are
3609 : * inside a function.
3610 : */
3611 : bool
1878 peter_e 3612 GIC 2525 : IsInTransactionBlock(bool isTopLevel)
3613 : {
3614 : /*
3615 : * Return true on same conditions that would make
3616 : * PreventInTransactionBlock error out
3617 : */
6896 tgl 3618 2525 : if (IsTransactionBlock())
3619 57 : return true;
3620 :
6856 3621 2468 : if (IsSubTransaction())
6856 tgl 3622 UIC 0 : return true;
3623 :
117 tgl 3624 CBC 2468 : if (MyXactFlags & XACT_FLAGS_PIPELINING)
117 tgl 3625 UIC 0 : return true;
3626 :
5871 tgl 3627 GIC 2468 : if (!isTopLevel)
6896 3628 53 : return true;
3629 :
6896 tgl 3630 CBC 2415 : if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
3631 2415 : CurrentTransactionState->blockState != TBLOCK_STARTED)
6896 tgl 3632 UIC 0 : return true;
6896 tgl 3633 ECB :
6896 tgl 3634 GBC 2415 : return false;
3635 : }
6896 tgl 3636 ECB :
7475 tgl 3637 EUB :
3638 : /*
6825 tgl 3639 ECB : * Register or deregister callback functions for start- and end-of-xact
3640 : * operations.
3641 : *
7133 3642 : * These functions are intended for use by dynamically loaded modules.
3643 : * For built-in modules we generally just hardwire the appropriate calls
7133 tgl 3644 EUB : * (mainly because it's easier to control the order that way, where needed).
3645 : *
6825 tgl 3646 ECB : * At transaction end, the callback occurs post-commit or post-abort, so the
3647 : * callback functions can only do noncritical cleanup.
3648 : */
3649 : void
6825 tgl 3650 GIC 1770 : RegisterXactCallback(XactCallback callback, void *arg)
3651 : {
3652 : XactCallbackItem *item;
3653 :
3654 : item = (XactCallbackItem *)
3655 1770 : MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
7133 3656 1770 : item->callback = callback;
3657 1770 : item->arg = arg;
6825 3658 1770 : item->next = Xact_callbacks;
3659 1770 : Xact_callbacks = item;
7133 3660 1770 : }
3661 :
7133 tgl 3662 ECB : void
6825 tgl 3663 UIC 0 : UnregisterXactCallback(XactCallback callback, void *arg)
3664 : {
3665 : XactCallbackItem *item;
3666 : XactCallbackItem *prev;
7133 tgl 3667 ECB :
7133 tgl 3668 LBC 0 : prev = NULL;
6825 3669 0 : for (item = Xact_callbacks; item; prev = item, item = item->next)
7133 tgl 3670 ECB : {
7133 tgl 3671 LBC 0 : if (item->callback == callback && item->arg == arg)
7133 tgl 3672 ECB : {
7133 tgl 3673 UIC 0 : if (prev)
3674 0 : prev->next = item->next;
7133 tgl 3675 EUB : else
6825 tgl 3676 UIC 0 : Xact_callbacks = item->next;
7133 3677 0 : pfree(item);
3678 0 : break;
3679 : }
7133 tgl 3680 EUB : }
7133 tgl 3681 UBC 0 : }
3682 :
7133 tgl 3683 EUB : static void
6779 tgl 3684 GIC 950898 : CallXactCallbacks(XactEvent event)
7133 tgl 3685 EUB : {
6825 3686 : XactCallbackItem *item;
3687 : XactCallbackItem *next;
3688 :
193 tgl 3689 GNC 1177686 : for (item = Xact_callbacks; item; item = next)
3690 : {
3691 : /* allow callbacks to unregister themselves when called */
3692 226789 : next = item->next;
2040 peter_e 3693 GBC 226789 : item->callback(event, item->arg);
3694 : }
6779 tgl 3695 950897 : }
3696 :
3697 :
6779 tgl 3698 EUB : /*
3699 : * Register or deregister callback functions for start- and end-of-subxact
3700 : * operations.
6779 tgl 3701 ECB : *
3702 : * Pretty much same as above, but for subtransaction events.
3703 : *
3704 : * At subtransaction end, the callback occurs post-subcommit or post-subabort,
3705 : * so the callback functions can only do noncritical cleanup. At
3706 : * subtransaction start, the callback is called when the subtransaction has
3707 : * finished initializing.
3708 : */
3709 : void
6779 tgl 3710 CBC 1770 : RegisterSubXactCallback(SubXactCallback callback, void *arg)
3711 : {
6779 tgl 3712 ECB : SubXactCallbackItem *item;
3713 :
3714 : item = (SubXactCallbackItem *)
6779 tgl 3715 GIC 1770 : MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
3716 1770 : item->callback = callback;
3717 1770 : item->arg = arg;
3718 1770 : item->next = SubXact_callbacks;
3719 1770 : SubXact_callbacks = item;
3720 1770 : }
3721 :
3722 : void
6779 tgl 3723 UIC 0 : UnregisterSubXactCallback(SubXactCallback callback, void *arg)
3724 : {
3725 : SubXactCallbackItem *item;
3726 : SubXactCallbackItem *prev;
6779 tgl 3727 ECB :
6779 tgl 3728 UIC 0 : prev = NULL;
3729 0 : for (item = SubXact_callbacks; item; prev = item, item = item->next)
3730 : {
3731 0 : if (item->callback == callback && item->arg == arg)
6779 tgl 3732 ECB : {
6779 tgl 3733 LBC 0 : if (prev)
3734 0 : prev->next = item->next;
6779 tgl 3735 ECB : else
6779 tgl 3736 LBC 0 : SubXact_callbacks = item->next;
3737 0 : pfree(item);
6779 tgl 3738 UIC 0 : break;
3739 : }
6779 tgl 3740 EUB : }
6779 tgl 3741 UIC 0 : }
3742 :
3743 : static void
6779 tgl 3744 GIC 21881 : CallSubXactCallbacks(SubXactEvent event,
6779 tgl 3745 EUB : SubTransactionId mySubid,
3746 : SubTransactionId parentSubid)
3747 : {
3748 : SubXactCallbackItem *item;
3749 : SubXactCallbackItem *next;
3750 :
193 tgl 3751 GNC 38344 : for (item = SubXact_callbacks; item; item = next)
3752 : {
3753 : /* allow callbacks to unregister themselves when called */
3754 16463 : next = item->next;
2040 peter_e 3755 GBC 16463 : item->callback(event, mySubid, parentSubid, item->arg);
3756 : }
7133 tgl 3757 GIC 21881 : }
7133 tgl 3758 EUB :
3759 :
9345 bruce 3760 : /* ----------------------------------------------------------------
3761 : * transaction block support
3762 : * ----------------------------------------------------------------
3763 : */
3764 :
3765 : /*
7452 bruce 3766 ECB : * BeginTransactionBlock
3767 : * This executes a BEGIN command.
3768 : */
3769 : void
9345 bruce 3770 GIC 7436 : BeginTransactionBlock(void)
3771 : {
3772 7436 : TransactionState s = CurrentTransactionState;
9345 bruce 3773 ECB :
6830 tgl 3774 GIC 7436 : switch (s->blockState)
3775 : {
6943 bruce 3776 ECB : /*
6385 3777 : * We are not inside a transaction block, so allow one to begin.
3778 : */
6943 bruce 3779 CBC 6960 : case TBLOCK_STARTED:
6943 bruce 3780 GIC 6960 : s->blockState = TBLOCK_BEGIN;
3781 6960 : break;
3782 :
3783 : /*
3784 : * BEGIN converts an implicit transaction block to a regular one.
3785 : * (Note that we allow this even if we've already done some
3786 : * commands, which is a bit odd but matches historical practice.)
3787 : */
2040 tgl 3788 476 : case TBLOCK_IMPLICIT_INPROGRESS:
3789 476 : s->blockState = TBLOCK_BEGIN;
3790 476 : break;
3791 :
6856 tgl 3792 ECB : /*
3793 : * Already a transaction block in progress.
3794 : */
6943 bruce 3795 UIC 0 : case TBLOCK_INPROGRESS:
2901 rhaas 3796 ECB : case TBLOCK_PARALLEL_INPROGRESS:
3797 : case TBLOCK_SUBINPROGRESS:
3798 : case TBLOCK_ABORT:
3799 : case TBLOCK_SUBABORT:
6830 tgl 3800 UIC 0 : ereport(WARNING,
6830 tgl 3801 ECB : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
6385 bruce 3802 : errmsg("there is already a transaction in progress")));
6943 bruce 3803 LBC 0 : break;
3804 :
3805 : /* These cases are invalid. */
6943 bruce 3806 UIC 0 : case TBLOCK_DEFAULT:
3807 : case TBLOCK_BEGIN:
3808 : case TBLOCK_SUBBEGIN:
3809 : case TBLOCK_END:
4282 simon 3810 ECB : case TBLOCK_SUBRELEASE:
3811 : case TBLOCK_SUBCOMMIT:
6779 tgl 3812 : case TBLOCK_ABORT_END:
3813 : case TBLOCK_SUBABORT_END:
3814 : case TBLOCK_ABORT_PENDING:
3815 : case TBLOCK_SUBABORT_PENDING:
3816 : case TBLOCK_SUBRESTART:
6779 tgl 3817 EUB : case TBLOCK_SUBABORT_RESTART:
3818 : case TBLOCK_PREPARE:
6856 tgl 3819 UIC 0 : elog(FATAL, "BeginTransactionBlock: unexpected state %s",
3820 : BlockStateAsString(s->blockState));
3821 : break;
6943 bruce 3822 EUB : }
9770 scrappy 3823 GIC 7436 : }
3824 :
6505 tgl 3825 EUB : /*
3826 : * PrepareTransactionBlock
3827 : * This executes a PREPARE command.
3828 : *
3829 : * Since PREPARE may actually do a ROLLBACK, the result indicates what
3830 : * happened: true for PREPARE, false for ROLLBACK.
3831 : *
3832 : * Note that we don't actually do anything here except change blockState.
3833 : * The real work will be done in the upcoming PrepareTransaction().
3834 : * We do it this way because it's not convenient to change memory context,
3835 : * resource owner, etc while executing inside a Portal.
3836 : */
3837 : bool
1986 peter_e 3838 GIC 404 : PrepareTransactionBlock(const char *gid)
3839 : {
3840 : TransactionState s;
6385 bruce 3841 EUB : bool result;
3842 :
3843 : /* Set up to commit the current transaction */
1477 peter 3844 GIC 404 : result = EndTransactionBlock(false);
6505 tgl 3845 ECB :
3846 : /* If successful, change outer tblock state to PREPARE */
6505 tgl 3847 GIC 404 : if (result)
3848 : {
3849 402 : s = CurrentTransactionState;
3850 :
3851 555 : while (s->parent != NULL)
3852 153 : s = s->parent;
3853 :
3854 402 : if (s->blockState == TBLOCK_END)
3855 : {
3856 : /* Save GID where PrepareTransaction can find it again */
3857 402 : prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
3858 :
3859 402 : s->blockState = TBLOCK_PREPARE;
6505 tgl 3860 ECB : }
3861 : else
3862 : {
3863 : /*
3864 : * ignore case where we are not in a transaction;
3865 : * EndTransactionBlock already issued a warning.
3866 : */
2040 tgl 3867 UIC 0 : Assert(s->blockState == TBLOCK_STARTED ||
3868 : s->blockState == TBLOCK_IMPLICIT_INPROGRESS);
6505 tgl 3869 ECB : /* Don't send back a PREPARE result tag... */
6505 tgl 3870 UIC 0 : result = false;
6505 tgl 3871 ECB : }
3872 : }
3873 :
6505 tgl 3874 CBC 404 : return result;
3875 : }
6505 tgl 3876 ECB :
3877 : /*
3878 : * EndTransactionBlock
6856 3879 : * This executes a COMMIT command.
3880 : *
6830 3881 : * Since COMMIT may actually do a ROLLBACK, the result indicates what
3882 : * happened: true for COMMIT, false for ROLLBACK.
3883 : *
3884 : * Note that we don't actually do anything here except change blockState.
3885 : * The real work will be done in the upcoming CommitTransactionCommand().
3886 : * We do it this way because it's not convenient to change memory context,
3887 : * resource owner, etc while executing inside a Portal.
3888 : */
6830 tgl 3889 EUB : bool
1477 peter 3890 GIC 6178 : EndTransactionBlock(bool chain)
3891 : {
9345 bruce 3892 GBC 6178 : TransactionState s = CurrentTransactionState;
6830 tgl 3893 GIC 6178 : bool result = false;
3894 :
3895 6178 : switch (s->blockState)
6830 tgl 3896 ECB : {
3897 : /*
3898 : * We are in a transaction block, so tell CommitTransactionCommand
3899 : * to COMMIT.
3900 : */
6943 bruce 3901 GIC 5271 : case TBLOCK_INPROGRESS:
6830 tgl 3902 5271 : s->blockState = TBLOCK_END;
3903 5271 : result = true;
6856 3904 5271 : break;
3905 :
3906 : /*
3907 : * We are in an implicit transaction block. If AND CHAIN was
3908 : * specified, error. Otherwise commit, but issue a warning
3909 : * because there was no explicit BEGIN before this.
3910 : */
2040 3911 24 : case TBLOCK_IMPLICIT_INPROGRESS:
1309 peter 3912 CBC 24 : if (chain)
1309 peter 3913 GIC 12 : ereport(ERROR,
1309 peter 3914 ECB : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1060 tgl 3915 : /* translator: %s represents an SQL statement name */
3916 : errmsg("%s can only be used in transaction blocks",
1309 peter 3917 : "COMMIT AND CHAIN")));
3918 : else
1309 peter 3919 GIC 12 : ereport(WARNING,
3920 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3921 : errmsg("there is no transaction in progress")));
2040 tgl 3922 12 : s->blockState = TBLOCK_END;
2040 tgl 3923 CBC 12 : result = true;
3924 12 : break;
2040 tgl 3925 ECB :
6943 bruce 3926 : /*
3927 : * We are in a failed transaction block. Tell
3928 : * CommitTransactionCommand it's time to exit the block.
3929 : */
6943 bruce 3930 GIC 338 : case TBLOCK_ABORT:
6779 tgl 3931 338 : s->blockState = TBLOCK_ABORT_END;
6943 bruce 3932 338 : break;
9770 scrappy 3933 ECB :
6785 tgl 3934 : /*
6385 bruce 3935 : * We are in a live subtransaction block. Set up to subcommit all
3936 : * open subtransactions and then commit the main transaction.
3937 : */
6785 tgl 3938 GIC 503 : case TBLOCK_SUBINPROGRESS:
3939 1073 : while (s->parent != NULL)
3940 : {
6779 tgl 3941 CBC 570 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4282 simon 3942 GIC 570 : s->blockState = TBLOCK_SUBCOMMIT;
3943 : else
6779 tgl 3944 LBC 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
6779 tgl 3945 ECB : BlockStateAsString(s->blockState));
6785 tgl 3946 CBC 570 : s = s->parent;
3947 : }
6779 tgl 3948 GIC 503 : if (s->blockState == TBLOCK_INPROGRESS)
3949 503 : s->blockState = TBLOCK_END;
3950 : else
6779 tgl 3951 UIC 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
6779 tgl 3952 ECB : BlockStateAsString(s->blockState));
6785 tgl 3953 CBC 503 : result = true;
3954 503 : break;
3955 :
3956 : /*
3957 : * Here we are inside an aborted subtransaction. Treat the COMMIT
3958 : * as ROLLBACK: set up to abort everything and exit the main
3959 : * transaction.
6856 tgl 3960 ECB : */
6856 tgl 3961 CBC 30 : case TBLOCK_SUBABORT:
6779 tgl 3962 GIC 60 : while (s->parent != NULL)
6779 tgl 3963 ECB : {
6779 tgl 3964 CBC 30 : if (s->blockState == TBLOCK_SUBINPROGRESS)
6779 tgl 3965 UIC 0 : s->blockState = TBLOCK_SUBABORT_PENDING;
6779 tgl 3966 GBC 30 : else if (s->blockState == TBLOCK_SUBABORT)
6779 tgl 3967 GIC 30 : s->blockState = TBLOCK_SUBABORT_END;
6779 tgl 3968 ECB : else
6779 tgl 3969 UIC 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
6779 tgl 3970 ECB : BlockStateAsString(s->blockState));
6779 tgl 3971 CBC 30 : s = s->parent;
3972 : }
6779 tgl 3973 GBC 30 : if (s->blockState == TBLOCK_INPROGRESS)
6779 tgl 3974 GIC 30 : s->blockState = TBLOCK_ABORT_PENDING;
6779 tgl 3975 LBC 0 : else if (s->blockState == TBLOCK_ABORT)
3976 0 : s->blockState = TBLOCK_ABORT_END;
3977 : else
6779 tgl 3978 UIC 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
3979 : BlockStateAsString(s->blockState));
6856 tgl 3980 GIC 30 : break;
3981 :
3982 : /*
1309 peter 3983 ECB : * The user issued COMMIT when not inside a transaction. For
3984 : * COMMIT without CHAIN, issue a WARNING, staying in
3985 : * TBLOCK_STARTED state. The upcoming call to
6735 tgl 3986 : * CommitTransactionCommand() will then close the transaction and
1309 peter 3987 EUB : * put us back into the default state. For COMMIT AND CHAIN,
1309 peter 3988 ECB : * error.
6943 bruce 3989 : */
6779 tgl 3990 GIC 12 : case TBLOCK_STARTED:
1309 peter 3991 GBC 12 : if (chain)
1309 peter 3992 GIC 3 : ereport(ERROR,
1309 peter 3993 ECB : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3994 : /* translator: %s represents an SQL statement name */
3995 : errmsg("%s can only be used in transaction blocks",
3996 : "COMMIT AND CHAIN")));
1309 peter 3997 EUB : else
1309 peter 3998 GBC 9 : ereport(WARNING,
3999 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1309 peter 4000 EUB : errmsg("there is no transaction in progress")));
6735 tgl 4001 GIC 9 : result = true;
6943 bruce 4002 CBC 9 : break;
4003 :
4004 : /*
4005 : * The user issued a COMMIT that somehow ran inside a parallel
4006 : * worker. We can't cope with that.
4007 : */
2901 rhaas 4008 UIC 0 : case TBLOCK_PARALLEL_INPROGRESS:
4009 0 : ereport(FATAL,
4010 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4011 : errmsg("cannot commit during a parallel operation")));
2901 rhaas 4012 ECB : break;
4013 :
6779 tgl 4014 : /* These cases are invalid. */
6943 bruce 4015 UIC 0 : case TBLOCK_DEFAULT:
4016 : case TBLOCK_BEGIN:
4017 : case TBLOCK_SUBBEGIN:
4018 : case TBLOCK_END:
4019 : case TBLOCK_SUBRELEASE:
4282 simon 4020 ECB : case TBLOCK_SUBCOMMIT:
4021 : case TBLOCK_ABORT_END:
4022 : case TBLOCK_SUBABORT_END:
6779 tgl 4023 : case TBLOCK_ABORT_PENDING:
6830 4024 : case TBLOCK_SUBABORT_PENDING:
4025 : case TBLOCK_SUBRESTART:
4026 : case TBLOCK_SUBABORT_RESTART:
4027 : case TBLOCK_PREPARE:
6856 tgl 4028 UIC 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4029 : BlockStateAsString(s->blockState));
6943 bruce 4030 EUB : break;
9345 4031 : }
4032 :
1477 peter 4033 GIC 6163 : Assert(s->blockState == TBLOCK_STARTED ||
4034 : s->blockState == TBLOCK_END ||
4035 : s->blockState == TBLOCK_ABORT_END ||
4036 : s->blockState == TBLOCK_ABORT_PENDING);
1477 peter 4037 EUB :
1477 peter 4038 GIC 6163 : s->chain = chain;
4039 :
6830 tgl 4040 6163 : return result;
4041 : }
4042 :
4043 : /*
4044 : * UserAbortTransactionBlock
4045 : * This executes a ROLLBACK command.
4046 : *
4047 : * As above, we don't actually do anything here except change blockState.
4048 : */
4049 : void
1477 peter 4050 GBC 1160 : UserAbortTransactionBlock(bool chain)
4051 : {
9345 bruce 4052 GIC 1160 : TransactionState s = CurrentTransactionState;
4053 :
6830 tgl 4054 1160 : switch (s->blockState)
6830 tgl 4055 ECB : {
4056 : /*
4057 : * We are inside a transaction block and we got a ROLLBACK command
4058 : * from the user, so tell CommitTransactionCommand to abort and
4059 : * exit the transaction block.
4060 : */
6779 tgl 4061 GIC 797 : case TBLOCK_INPROGRESS:
6779 tgl 4062 CBC 797 : s->blockState = TBLOCK_ABORT_PENDING;
6856 tgl 4063 GIC 797 : break;
4064 :
4065 : /*
4066 : * We are inside a failed transaction block and we got a ROLLBACK
4067 : * command from the user. Abort processing is already done, so
4068 : * CommitTransactionCommand just has to cleanup and go back to
4069 : * idle state.
4070 : */
6779 4071 274 : case TBLOCK_ABORT:
6779 tgl 4072 CBC 274 : s->blockState = TBLOCK_ABORT_END;
6856 tgl 4073 GIC 274 : break;
6856 tgl 4074 ECB :
4075 : /*
3260 bruce 4076 : * We are inside a subtransaction. Mark everything up to top
4077 : * level as exitable.
4078 : */
6856 tgl 4079 GIC 50 : case TBLOCK_SUBINPROGRESS:
4080 : case TBLOCK_SUBABORT:
6779 4081 203 : while (s->parent != NULL)
4082 : {
6779 tgl 4083 CBC 153 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4084 143 : s->blockState = TBLOCK_SUBABORT_PENDING;
4085 10 : else if (s->blockState == TBLOCK_SUBABORT)
6779 tgl 4086 GIC 10 : s->blockState = TBLOCK_SUBABORT_END;
4087 : else
6779 tgl 4088 UIC 0 : elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
4089 : BlockStateAsString(s->blockState));
6779 tgl 4090 GIC 153 : s = s->parent;
4091 : }
4092 50 : if (s->blockState == TBLOCK_INPROGRESS)
6779 tgl 4093 CBC 50 : s->blockState = TBLOCK_ABORT_PENDING;
6779 tgl 4094 LBC 0 : else if (s->blockState == TBLOCK_ABORT)
4095 0 : s->blockState = TBLOCK_ABORT_END;
4096 : else
6779 tgl 4097 UIC 0 : elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
4098 : BlockStateAsString(s->blockState));
6856 tgl 4099 GIC 50 : break;
4100 :
6856 tgl 4101 ECB : /*
4102 : * The user issued ABORT when not inside a transaction. For
1309 peter 4103 : * ROLLBACK without CHAIN, issue a WARNING and go to abort state.
4104 : * The upcoming call to CommitTransactionCommand() will then put
4105 : * us back into the default state. For ROLLBACK AND CHAIN, error.
2040 tgl 4106 : *
4107 : * We do the same thing with ABORT inside an implicit transaction,
4108 : * although in this case we might be rolling back actual database
4109 : * state changes. (It's debatable whether we should issue a
2040 tgl 4110 EUB : * WARNING in this case, but we have done so historically.)
4111 : */
6856 tgl 4112 CBC 39 : case TBLOCK_STARTED:
4113 : case TBLOCK_IMPLICIT_INPROGRESS:
1309 peter 4114 39 : if (chain)
4115 15 : ereport(ERROR,
1309 peter 4116 EUB : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1060 tgl 4117 : /* translator: %s represents an SQL statement name */
4118 : errmsg("%s can only be used in transaction blocks",
1309 peter 4119 : "ROLLBACK AND CHAIN")));
4120 : else
1309 peter 4121 CBC 24 : ereport(WARNING,
4122 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4123 : errmsg("there is no transaction in progress")));
6779 tgl 4124 GIC 24 : s->blockState = TBLOCK_ABORT_PENDING;
6856 4125 24 : break;
4126 :
4127 : /*
4128 : * The user issued an ABORT that somehow ran inside a parallel
4129 : * worker. We can't cope with that.
4130 : */
2901 rhaas 4131 UIC 0 : case TBLOCK_PARALLEL_INPROGRESS:
4132 0 : ereport(FATAL,
4133 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2901 rhaas 4134 ECB : errmsg("cannot abort during a parallel operation")));
4135 : break;
4136 :
6830 tgl 4137 : /* These cases are invalid. */
6856 tgl 4138 UIC 0 : case TBLOCK_DEFAULT:
4139 : case TBLOCK_BEGIN:
4140 : case TBLOCK_SUBBEGIN:
4141 : case TBLOCK_END:
4142 : case TBLOCK_SUBRELEASE:
4282 simon 4143 ECB : case TBLOCK_SUBCOMMIT:
4144 : case TBLOCK_ABORT_END:
4145 : case TBLOCK_SUBABORT_END:
6779 tgl 4146 : case TBLOCK_ABORT_PENDING:
6830 4147 : case TBLOCK_SUBABORT_PENDING:
4148 : case TBLOCK_SUBRESTART:
4149 : case TBLOCK_SUBABORT_RESTART:
4150 : case TBLOCK_PREPARE:
6856 tgl 4151 UIC 0 : elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
4152 : BlockStateAsString(s->blockState));
6856 tgl 4153 EUB : break;
9345 bruce 4154 : }
4155 :
1477 peter 4156 GIC 1145 : Assert(s->blockState == TBLOCK_ABORT_END ||
4157 : s->blockState == TBLOCK_ABORT_PENDING);
4158 :
4159 1145 : s->chain = chain;
6830 tgl 4160 GBC 1145 : }
4161 :
4162 : /*
4163 : * BeginImplicitTransactionBlock
4164 : * Start an implicit transaction block if we're not already in one.
4165 : *
4166 : * Unlike BeginTransactionBlock, this is called directly from the main loop
4167 : * in postgres.c, not within a Portal. So we can just change blockState
4168 : * without a lot of ceremony. We do not expect caller to do
4169 : * CommitTransactionCommand/StartTransactionCommand.
4170 : */
4171 : void
2040 tgl 4172 GIC 58453 : BeginImplicitTransactionBlock(void)
2040 tgl 4173 EUB : {
2040 tgl 4174 GIC 58453 : TransactionState s = CurrentTransactionState;
4175 :
4176 : /*
4177 : * If we are in STARTED state (that is, no transaction block is open),
2040 tgl 4178 ECB : * switch to IMPLICIT_INPROGRESS state, creating an implicit transaction
4179 : * block.
4180 : *
4181 : * For caller convenience, we consider all other transaction states as
4182 : * legal here; otherwise the caller would need its own state check, which
4183 : * seems rather pointless.
4184 : */
2040 tgl 4185 GIC 58453 : if (s->blockState == TBLOCK_STARTED)
4186 16191 : s->blockState = TBLOCK_IMPLICIT_INPROGRESS;
4187 58453 : }
4188 :
4189 : /*
4190 : * EndImplicitTransactionBlock
4191 : * End an implicit transaction block, if we're in one.
4192 : *
4193 : * Like EndTransactionBlock, we just make any needed blockState change here.
2040 tgl 4194 ECB : * The real work will be done in the upcoming CommitTransactionCommand().
4195 : */
4196 : void
2040 tgl 4197 GIC 16170 : EndImplicitTransactionBlock(void)
4198 : {
4199 16170 : TransactionState s = CurrentTransactionState;
4200 :
4201 : /*
4202 : * If we are in IMPLICIT_INPROGRESS state, switch back to STARTED state,
4203 : * allowing CommitTransactionCommand to commit whatever happened during
4204 : * the implicit transaction block as though it were a single statement.
4205 : *
4206 : * For caller convenience, we consider all other transaction states as
2040 tgl 4207 ECB : * legal here; otherwise the caller would need its own state check, which
4208 : * seems rather pointless.
4209 : */
2040 tgl 4210 GIC 16170 : if (s->blockState == TBLOCK_IMPLICIT_INPROGRESS)
4211 15642 : s->blockState = TBLOCK_STARTED;
4212 16170 : }
4213 :
4214 : /*
4215 : * DefineSavepoint
4216 : * This executes a SAVEPOINT command.
4217 : */
4218 : void
1986 peter_e 4219 CBC 1353 : DefineSavepoint(const char *name)
4220 : {
6797 bruce 4221 1353 : TransactionState s = CurrentTransactionState;
4222 :
4223 : /*
4224 : * Workers synchronize transaction state at the beginning of each parallel
4225 : * operation, so we can't account for new subtransactions after that
4226 : * point. (Note that this check will certainly error out if s->blockState
4227 : * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
4228 : * below.)
4229 : */
2901 rhaas 4230 GIC 1353 : if (IsInParallelMode())
2901 rhaas 4231 UIC 0 : ereport(ERROR,
2901 rhaas 4232 ECB : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2118 tgl 4233 : errmsg("cannot define savepoints during a parallel operation")));
2901 rhaas 4234 :
6830 tgl 4235 GIC 1353 : switch (s->blockState)
4236 : {
4237 1347 : case TBLOCK_INPROGRESS:
4238 : case TBLOCK_SUBINPROGRESS:
4239 : /* Normal subtransaction start */
4240 1347 : PushTransaction();
2118 tgl 4241 CBC 1347 : s = CurrentTransactionState; /* changed by push */
4242 :
6830 tgl 4243 ECB : /*
4244 : * Savepoint names, like the TransactionState block itself, live
4245 : * in TopTransactionContext.
4246 : */
6779 tgl 4247 GIC 1347 : if (name)
4248 999 : s->name = MemoryContextStrdup(TopTransactionContext, name);
6830 4249 1347 : break;
4250 :
4251 : /*
2040 tgl 4252 ECB : * We disallow savepoint commands in implicit transaction blocks.
2040 tgl 4253 EUB : * There would be no great difficulty in allowing them so far as
4254 : * this module is concerned, but a savepoint seems inconsistent
4255 : * with exec_simple_query's behavior of abandoning the whole query
4256 : * string upon error. Also, the point of an implicit transaction
2040 tgl 4257 ECB : * block (as opposed to a regular one) is to automatically close
4258 : * after an error, so it's hard to see how a savepoint would fit
4259 : * into that.
4260 : *
4261 : * The error messages for this are phrased as if there were no
4262 : * active transaction block at all, which is historical but
4263 : * perhaps could be improved.
4264 : */
2040 tgl 4265 GIC 6 : case TBLOCK_IMPLICIT_INPROGRESS:
4266 6 : ereport(ERROR,
4267 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4268 : /* translator: %s represents an SQL statement name */
2040 tgl 4269 ECB : errmsg("%s can only be used in transaction blocks",
4270 : "SAVEPOINT")));
4271 : break;
4272 :
4273 : /* These cases are invalid. */
6830 tgl 4274 UIC 0 : case TBLOCK_DEFAULT:
4275 : case TBLOCK_STARTED:
4276 : case TBLOCK_BEGIN:
4277 : case TBLOCK_PARALLEL_INPROGRESS:
4278 : case TBLOCK_SUBBEGIN:
4279 : case TBLOCK_END:
4280 : case TBLOCK_SUBRELEASE:
4281 : case TBLOCK_SUBCOMMIT:
4282 : case TBLOCK_ABORT:
4283 : case TBLOCK_SUBABORT:
4284 : case TBLOCK_ABORT_END:
4285 : case TBLOCK_SUBABORT_END:
4286 : case TBLOCK_ABORT_PENDING:
6830 tgl 4287 ECB : case TBLOCK_SUBABORT_PENDING:
6779 4288 : case TBLOCK_SUBRESTART:
4289 : case TBLOCK_SUBABORT_RESTART:
4290 : case TBLOCK_PREPARE:
6826 tgl 4291 UIC 0 : elog(FATAL, "DefineSavepoint: unexpected state %s",
4292 : BlockStateAsString(s->blockState));
4293 : break;
4294 : }
6830 tgl 4295 GIC 1347 : }
6830 tgl 4296 EUB :
4297 : /*
4298 : * ReleaseSavepoint
4299 : * This executes a RELEASE command.
4300 : *
4301 : * As above, we don't actually do anything here except change blockState.
4302 : */
4303 : void
1878 peter_e 4304 GIC 138 : ReleaseSavepoint(const char *name)
4305 : {
6797 bruce 4306 138 : TransactionState s = CurrentTransactionState;
4307 : TransactionState target,
4308 : xact;
4309 :
4310 : /*
4311 : * Workers synchronize transaction state at the beginning of each parallel
4312 : * operation, so we can't account for transaction state change after that
2901 rhaas 4313 EUB : * point. (Note that this check will certainly error out if s->blockState
4314 : * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
4315 : * below.)
4316 : */
2901 rhaas 4317 CBC 138 : if (IsInParallelMode())
2901 rhaas 4318 UIC 0 : ereport(ERROR,
4319 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4320 : errmsg("cannot release savepoints during a parallel operation")));
4321 :
6830 tgl 4322 GIC 138 : switch (s->blockState)
4323 : {
4324 : /*
4325 : * We can't release a savepoint if there is no savepoint defined.
6779 tgl 4326 ECB : */
6830 tgl 4327 UIC 0 : case TBLOCK_INPROGRESS:
6830 tgl 4328 LBC 0 : ereport(ERROR,
4329 : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4330 : errmsg("savepoint \"%s\" does not exist", name)));
4331 : break;
4332 :
2040 tgl 4333 GIC 3 : case TBLOCK_IMPLICIT_INPROGRESS:
4334 : /* See comment about implicit transactions in DefineSavepoint */
4335 3 : ereport(ERROR,
4336 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4337 : /* translator: %s represents an SQL statement name */
4338 : errmsg("%s can only be used in transaction blocks",
2040 tgl 4339 ECB : "RELEASE SAVEPOINT")));
2040 tgl 4340 EUB : break;
4341 :
4342 : /*
4343 : * We are in a non-aborted subtransaction. This is the only valid
6385 bruce 4344 ECB : * case.
4345 : */
6830 tgl 4346 GIC 135 : case TBLOCK_SUBINPROGRESS:
4347 135 : break;
4348 :
6779 tgl 4349 EUB : /* These cases are invalid. */
6830 tgl 4350 UBC 0 : case TBLOCK_DEFAULT:
4351 : case TBLOCK_STARTED:
4352 : case TBLOCK_BEGIN:
4353 : case TBLOCK_PARALLEL_INPROGRESS:
4354 : case TBLOCK_SUBBEGIN:
6779 tgl 4355 ECB : case TBLOCK_END:
4356 : case TBLOCK_SUBRELEASE:
4282 simon 4357 : case TBLOCK_SUBCOMMIT:
4358 : case TBLOCK_ABORT:
4359 : case TBLOCK_SUBABORT:
4360 : case TBLOCK_ABORT_END:
4361 : case TBLOCK_SUBABORT_END:
4362 : case TBLOCK_ABORT_PENDING:
4363 : case TBLOCK_SUBABORT_PENDING:
4364 : case TBLOCK_SUBRESTART:
4365 : case TBLOCK_SUBABORT_RESTART:
4366 : case TBLOCK_PREPARE:
6830 tgl 4367 UIC 0 : elog(FATAL, "ReleaseSavepoint: unexpected state %s",
6830 tgl 4368 ECB : BlockStateAsString(s->blockState));
4369 : break;
4370 : }
4371 :
6801 tgl 4372 GBC 221 : for (target = s; PointerIsValid(target); target = target->parent)
4373 : {
6830 tgl 4374 GIC 221 : if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
4375 135 : break;
4376 : }
4377 :
4378 135 : if (!PointerIsValid(target))
6830 tgl 4379 UIC 0 : ereport(ERROR,
4380 : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4381 : errmsg("savepoint \"%s\" does not exist", name)));
4382 :
4383 : /* disallow crossing savepoint level boundaries */
6801 tgl 4384 GIC 135 : if (target->savepointLevel != s->savepointLevel)
6801 tgl 4385 UIC 0 : ereport(ERROR,
4386 : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4387 : errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
4388 :
6801 tgl 4389 EUB : /*
4390 : * Mark "commit pending" all subtransactions up to the target
4391 : * subtransaction. The actual commits will happen when control gets to
4392 : * CommitTransactionCommand.
4393 : */
6801 tgl 4394 CBC 135 : xact = CurrentTransactionState;
4395 : for (;;)
6801 tgl 4396 ECB : {
6801 tgl 4397 CBC 221 : Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
4282 simon 4398 GIC 221 : xact->blockState = TBLOCK_SUBRELEASE;
6801 tgl 4399 221 : if (xact == target)
6801 tgl 4400 CBC 135 : break;
6801 tgl 4401 GBC 86 : xact = xact->parent;
6801 tgl 4402 GIC 86 : Assert(PointerIsValid(xact));
4403 : }
6830 4404 135 : }
4405 :
6830 tgl 4406 ECB : /*
6830 tgl 4407 EUB : * RollbackToSavepoint
4408 : * This executes a ROLLBACK TO <savepoint> command.
4409 : *
4410 : * As above, we don't actually do anything here except change blockState.
4411 : */
4412 : void
1878 peter_e 4413 GIC 354 : RollbackToSavepoint(const char *name)
4414 : {
6830 tgl 4415 354 : TransactionState s = CurrentTransactionState;
6830 tgl 4416 ECB : TransactionState target,
4417 : xact;
4418 :
2901 rhaas 4419 : /*
4420 : * Workers synchronize transaction state at the beginning of each parallel
4421 : * operation, so we can't account for transaction state change after that
4422 : * point. (Note that this check will certainly error out if s->blockState
4423 : * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
4424 : * below.)
4425 : */
2901 rhaas 4426 CBC 354 : if (IsInParallelMode())
2901 rhaas 4427 UIC 0 : ereport(ERROR,
4428 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4429 : errmsg("cannot rollback to savepoints during a parallel operation")));
4430 :
6830 tgl 4431 GIC 354 : switch (s->blockState)
4432 : {
4433 : /*
4434 : * We can't rollback to a savepoint if there is no savepoint
6797 bruce 4435 ECB : * defined.
4436 : */
6830 tgl 4437 CBC 3 : case TBLOCK_INPROGRESS:
4438 : case TBLOCK_ABORT:
6830 tgl 4439 GIC 3 : ereport(ERROR,
4440 : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4441 : errmsg("savepoint \"%s\" does not exist", name)));
4442 : break;
4443 :
2040 4444 3 : case TBLOCK_IMPLICIT_INPROGRESS:
4445 : /* See comment about implicit transactions in DefineSavepoint */
4446 3 : ereport(ERROR,
4447 : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2040 tgl 4448 ECB : /* translator: %s represents an SQL statement name */
2040 tgl 4449 EUB : errmsg("%s can only be used in transaction blocks",
4450 : "ROLLBACK TO SAVEPOINT")));
4451 : break;
4452 :
6830 tgl 4453 ECB : /*
4454 : * There is at least one savepoint, so proceed.
4455 : */
6830 tgl 4456 GIC 348 : case TBLOCK_SUBINPROGRESS:
4457 : case TBLOCK_SUBABORT:
4458 348 : break;
6830 tgl 4459 ECB :
4460 : /* These cases are invalid. */
6830 tgl 4461 LBC 0 : case TBLOCK_DEFAULT:
4462 : case TBLOCK_STARTED:
4463 : case TBLOCK_BEGIN:
4464 : case TBLOCK_PARALLEL_INPROGRESS:
4465 : case TBLOCK_SUBBEGIN:
6830 tgl 4466 ECB : case TBLOCK_END:
4467 : case TBLOCK_SUBRELEASE:
4282 simon 4468 : case TBLOCK_SUBCOMMIT:
4469 : case TBLOCK_ABORT_END:
4470 : case TBLOCK_SUBABORT_END:
4471 : case TBLOCK_ABORT_PENDING:
4472 : case TBLOCK_SUBABORT_PENDING:
4473 : case TBLOCK_SUBRESTART:
4474 : case TBLOCK_SUBABORT_RESTART:
4475 : case TBLOCK_PREPARE:
6830 tgl 4476 UIC 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4477 : BlockStateAsString(s->blockState));
6830 tgl 4478 ECB : break;
4479 : }
4480 :
6823 tgl 4481 GIC 373 : for (target = s; PointerIsValid(target); target = target->parent)
4482 : {
6830 tgl 4483 GBC 373 : if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
6830 tgl 4484 GIC 348 : break;
4485 : }
4486 :
4487 348 : if (!PointerIsValid(target))
6830 tgl 4488 UIC 0 : ereport(ERROR,
4489 : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4490 : errmsg("savepoint \"%s\" does not exist", name)));
4491 :
4492 : /* disallow crossing savepoint level boundaries */
6823 tgl 4493 GIC 348 : if (target->savepointLevel != s->savepointLevel)
6823 tgl 4494 UIC 0 : ereport(ERROR,
4495 : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4496 : errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
4497 :
6830 tgl 4498 EUB : /*
4499 : * Mark "abort pending" all subtransactions up to the target
4500 : * subtransaction. The actual aborts will happen when control gets to
4501 : * CommitTransactionCommand.
4502 : */
6830 tgl 4503 CBC 348 : xact = CurrentTransactionState;
4504 : for (;;)
6830 tgl 4505 ECB : {
6779 tgl 4506 CBC 373 : if (xact == target)
6779 tgl 4507 GIC 348 : break;
4508 25 : if (xact->blockState == TBLOCK_SUBINPROGRESS)
6779 tgl 4509 CBC 25 : xact->blockState = TBLOCK_SUBABORT_PENDING;
6779 tgl 4510 UBC 0 : else if (xact->blockState == TBLOCK_SUBABORT)
6779 tgl 4511 UIC 0 : xact->blockState = TBLOCK_SUBABORT_END;
4512 : else
4513 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4514 : BlockStateAsString(xact->blockState));
6830 tgl 4515 CBC 25 : xact = xact->parent;
6830 tgl 4516 GBC 25 : Assert(PointerIsValid(xact));
4517 : }
4518 :
4519 : /* And mark the target as "restart pending" */
6779 tgl 4520 GIC 348 : if (xact->blockState == TBLOCK_SUBINPROGRESS)
4521 252 : xact->blockState = TBLOCK_SUBRESTART;
4522 96 : else if (xact->blockState == TBLOCK_SUBABORT)
4523 96 : xact->blockState = TBLOCK_SUBABORT_RESTART;
4524 : else
6779 tgl 4525 LBC 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4526 : BlockStateAsString(xact->blockState));
6830 tgl 4527 GIC 348 : }
6830 tgl 4528 ECB :
4529 : /*
6826 4530 : * BeginInternalSubTransaction
5793 4531 : * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
2040 tgl 4532 EUB : * TBLOCK_IMPLICIT_INPROGRESS, TBLOCK_END, and TBLOCK_PREPARE states,
4533 : * and therefore it can safely be used in functions that might be called
4534 : * when not inside a BEGIN block or when running deferred triggers at
4535 : * COMMIT/PREPARE time. Also, it automatically does
4536 : * CommitTransactionCommand/StartTransactionCommand instead of expecting
2040 tgl 4537 ECB : * the caller to do it.
6826 4538 : */
4539 : void
1986 peter_e 4540 GIC 7436 : BeginInternalSubTransaction(const char *name)
4541 : {
6797 bruce 4542 CBC 7436 : TransactionState s = CurrentTransactionState;
6826 tgl 4543 ECB :
2901 rhaas 4544 : /*
4545 : * Workers synchronize transaction state at the beginning of each parallel
4546 : * operation, so we can't account for new subtransactions after that
2878 bruce 4547 EUB : * point. We might be able to make an exception for the type of
4548 : * subtransaction established by this function, which is typically used in
2878 bruce 4549 ECB : * contexts where we're going to release or roll back the subtransaction
4550 : * before proceeding further, so that no enduring change to the
4551 : * transaction state occurs. For now, however, we prohibit this case along
4552 : * with all the others.
4553 : */
2901 rhaas 4554 GIC 7436 : if (IsInParallelMode())
2901 rhaas 4555 UIC 0 : ereport(ERROR,
4556 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4557 : errmsg("cannot start subtransactions during a parallel operation")));
4558 :
6826 tgl 4559 GIC 7436 : switch (s->blockState)
4560 : {
4561 7436 : case TBLOCK_STARTED:
6826 tgl 4562 ECB : case TBLOCK_INPROGRESS:
4563 : case TBLOCK_IMPLICIT_INPROGRESS:
5793 4564 : case TBLOCK_END:
4565 : case TBLOCK_PREPARE:
4566 : case TBLOCK_SUBINPROGRESS:
4567 : /* Normal subtransaction start */
6826 tgl 4568 GIC 7436 : PushTransaction();
2118 4569 7436 : s = CurrentTransactionState; /* changed by push */
4570 :
4571 : /*
4572 : * Savepoint names, like the TransactionState block itself, live
4573 : * in TopTransactionContext.
4574 : */
6826 4575 7436 : if (name)
6779 tgl 4576 CBC 818 : s->name = MemoryContextStrdup(TopTransactionContext, name);
6826 tgl 4577 GBC 7436 : break;
4578 :
4579 : /* These cases are invalid. */
6826 tgl 4580 UIC 0 : case TBLOCK_DEFAULT:
6826 tgl 4581 ECB : case TBLOCK_BEGIN:
4582 : case TBLOCK_PARALLEL_INPROGRESS:
4583 : case TBLOCK_SUBBEGIN:
4584 : case TBLOCK_SUBRELEASE:
4585 : case TBLOCK_SUBCOMMIT:
4586 : case TBLOCK_ABORT:
4587 : case TBLOCK_SUBABORT:
4588 : case TBLOCK_ABORT_END:
4589 : case TBLOCK_SUBABORT_END:
6779 4590 : case TBLOCK_ABORT_PENDING:
6826 4591 : case TBLOCK_SUBABORT_PENDING:
4592 : case TBLOCK_SUBRESTART:
4593 : case TBLOCK_SUBABORT_RESTART:
6826 tgl 4594 UIC 0 : elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
4595 : BlockStateAsString(s->blockState));
4596 : break;
6826 tgl 4597 ECB : }
4598 :
6826 tgl 4599 CBC 7436 : CommitTransactionCommand();
6826 tgl 4600 GIC 7436 : StartTransactionCommand();
4601 7436 : }
6826 tgl 4602 EUB :
4603 : /*
4604 : * ReleaseCurrentSubTransaction
4605 : *
4606 : * RELEASE (ie, commit) the innermost subtransaction, regardless of its
4607 : * savepoint name (if any).
4608 : * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
4609 : */
4610 : void
6826 tgl 4611 GIC 3524 : ReleaseCurrentSubTransaction(void)
4612 : {
4613 3524 : TransactionState s = CurrentTransactionState;
4614 :
4615 : /*
2901 rhaas 4616 EUB : * Workers synchronize transaction state at the beginning of each parallel
4617 : * operation, so we can't account for commit of subtransactions after that
4618 : * point. This should not happen anyway. Code calling this would
4619 : * typically have called BeginInternalSubTransaction() first, failing
4620 : * there.
2901 rhaas 4621 ECB : */
2901 rhaas 4622 CBC 3524 : if (IsInParallelMode())
2901 rhaas 4623 LBC 0 : ereport(ERROR,
4624 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4625 : errmsg("cannot commit subtransactions during a parallel operation")));
4626 :
6826 tgl 4627 GIC 3524 : if (s->blockState != TBLOCK_SUBINPROGRESS)
6826 tgl 4628 UIC 0 : elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
4629 : BlockStateAsString(s->blockState));
6785 tgl 4630 GIC 3524 : Assert(s->state == TRANS_INPROGRESS);
6826 4631 3524 : MemoryContextSwitchTo(CurTransactionContext);
4232 simon 4632 3524 : CommitSubTransaction();
6385 bruce 4633 CBC 3524 : s = CurrentTransactionState; /* changed by pop */
6785 tgl 4634 GIC 3524 : Assert(s->state == TRANS_INPROGRESS);
6826 tgl 4635 CBC 3524 : }
4636 :
4637 : /*
4638 : * RollbackAndReleaseCurrentSubTransaction
4639 : *
4640 : * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
4641 : * of its savepoint name (if any).
4642 : * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
4643 : */
6830 tgl 4644 ECB : void
6826 tgl 4645 GBC 3912 : RollbackAndReleaseCurrentSubTransaction(void)
4646 : {
6826 tgl 4647 GIC 3912 : TransactionState s = CurrentTransactionState;
4648 :
2901 rhaas 4649 ECB : /*
2901 rhaas 4650 EUB : * Unlike ReleaseCurrentSubTransaction(), this is nominally permitted
4651 : * during parallel operations. That's because we may be in the leader,
2901 rhaas 4652 ECB : * recovering from an error thrown while we were in parallel mode. We
4653 : * won't reach here in a worker, because BeginInternalSubTransaction()
4654 : * will have failed.
4655 : */
4656 :
6826 tgl 4657 CBC 3912 : switch (s->blockState)
4658 : {
4659 : /* Must be in a subtransaction */
6826 tgl 4660 GIC 3912 : case TBLOCK_SUBINPROGRESS:
4661 : case TBLOCK_SUBABORT:
4662 3912 : break;
4663 :
4664 : /* These cases are invalid. */
6826 tgl 4665 UIC 0 : case TBLOCK_DEFAULT:
4666 : case TBLOCK_STARTED:
6826 tgl 4667 ECB : case TBLOCK_BEGIN:
4668 : case TBLOCK_IMPLICIT_INPROGRESS:
2901 rhaas 4669 : case TBLOCK_PARALLEL_INPROGRESS:
4670 : case TBLOCK_SUBBEGIN:
4671 : case TBLOCK_INPROGRESS:
4672 : case TBLOCK_END:
4673 : case TBLOCK_SUBRELEASE:
4674 : case TBLOCK_SUBCOMMIT:
4675 : case TBLOCK_ABORT:
4676 : case TBLOCK_ABORT_END:
4677 : case TBLOCK_SUBABORT_END:
4678 : case TBLOCK_ABORT_PENDING:
6826 tgl 4679 : case TBLOCK_SUBABORT_PENDING:
4680 : case TBLOCK_SUBRESTART:
4681 : case TBLOCK_SUBABORT_RESTART:
6505 4682 : case TBLOCK_PREPARE:
6826 tgl 4683 UIC 0 : elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
6826 tgl 4684 ECB : BlockStateAsString(s->blockState));
4685 : break;
4686 : }
6826 tgl 4687 EUB :
4688 : /*
4689 : * Abort the current subtransaction, if needed.
4690 : */
6826 tgl 4691 GIC 3912 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4692 3094 : AbortSubTransaction();
4693 :
4694 : /* And clean it up, too */
6779 4695 3912 : CleanupSubTransaction();
4696 :
4697 3912 : s = CurrentTransactionState; /* changed by pop */
163 peter 4698 GNC 3912 : Assert(s->blockState == TBLOCK_SUBINPROGRESS ||
4699 : s->blockState == TBLOCK_INPROGRESS ||
4700 : s->blockState == TBLOCK_IMPLICIT_INPROGRESS ||
4701 : s->blockState == TBLOCK_STARTED);
9770 scrappy 4702 GIC 3912 : }
4703 :
4704 : /*
7452 bruce 4705 EUB : * AbortOutOfAnyTransaction
4706 : *
4707 : * This routine is provided for error recovery purposes. It aborts any
4708 : * active transaction or transaction block, leaving the system in a known
4709 : * idle state.
4710 : */
4711 : void
8202 tgl 4712 GIC 11758 : AbortOutOfAnyTransaction(void)
8951 tgl 4713 ECB : {
8951 tgl 4714 CBC 11758 : TransactionState s = CurrentTransactionState;
4715 :
4716 : /* Ensure we're not running in a doomed memory context */
2064 4717 11758 : AtAbort_Memory();
4718 :
8951 tgl 4719 ECB : /*
6856 4720 : * Get out of any transaction or nested transaction
4721 : */
4722 : do
4723 : {
6856 tgl 4724 CBC 11758 : switch (s->blockState)
4725 : {
6856 tgl 4726 GIC 11392 : case TBLOCK_DEFAULT:
3968 4727 11392 : if (s->state == TRANS_DEFAULT)
4728 : {
4729 : /* Not in a transaction, do nothing */
4730 : }
4731 : else
4732 : {
4733 : /*
3968 tgl 4734 ECB : * We can get here after an error during transaction start
4735 : * (state will be TRANS_START). Need to clean up the
4736 : * incompletely started transaction. First, adjust the
4737 : * low-level state to suppress warning message from
4738 : * AbortTransaction.
4739 : */
3968 tgl 4740 UIC 0 : if (s->state == TRANS_START)
4741 0 : s->state = TRANS_INPROGRESS;
4742 0 : AbortTransaction();
4743 0 : CleanupTransaction();
4744 : }
6856 tgl 4745 GIC 11392 : break;
6856 tgl 4746 CBC 356 : case TBLOCK_STARTED:
4747 : case TBLOCK_BEGIN:
6856 tgl 4748 ECB : case TBLOCK_INPROGRESS:
2040 4749 : case TBLOCK_IMPLICIT_INPROGRESS:
4750 : case TBLOCK_PARALLEL_INPROGRESS:
4751 : case TBLOCK_END:
4752 : case TBLOCK_ABORT_PENDING:
4753 : case TBLOCK_PREPARE:
4754 : /* In a transaction, so clean up */
6856 tgl 4755 GIC 356 : AbortTransaction();
4756 356 : CleanupTransaction();
4757 356 : s->blockState = TBLOCK_DEFAULT;
4758 356 : break;
4759 10 : case TBLOCK_ABORT:
4760 : case TBLOCK_ABORT_END:
4761 :
2064 tgl 4762 EUB : /*
4763 : * AbortTransaction is already done, still need Cleanup.
4764 : * However, if we failed partway through running ROLLBACK,
4765 : * there will be an active portal running that command, which
4766 : * we need to shut down before doing CleanupTransaction.
2064 tgl 4767 ECB : */
2064 tgl 4768 CBC 10 : AtAbort_Portals();
6856 tgl 4769 GIC 10 : CleanupTransaction();
4770 10 : s->blockState = TBLOCK_DEFAULT;
4771 10 : break;
4772 :
4773 : /*
4774 : * In a subtransaction, so clean it up and abort parent too
4775 : */
6779 tgl 4776 UIC 0 : case TBLOCK_SUBBEGIN:
6856 tgl 4777 ECB : case TBLOCK_SUBINPROGRESS:
4282 simon 4778 : case TBLOCK_SUBRELEASE:
4779 : case TBLOCK_SUBCOMMIT:
6830 tgl 4780 : case TBLOCK_SUBABORT_PENDING:
6779 4781 : case TBLOCK_SUBRESTART:
6856 tgl 4782 UIC 0 : AbortSubTransaction();
4783 0 : CleanupSubTransaction();
6797 bruce 4784 0 : s = CurrentTransactionState; /* changed by pop */
6856 tgl 4785 0 : break;
4786 :
4787 0 : case TBLOCK_SUBABORT:
4788 : case TBLOCK_SUBABORT_END:
4789 : case TBLOCK_SUBABORT_RESTART:
6856 tgl 4790 ECB : /* As above, but AbortSubTransaction already done */
2064 tgl 4791 LBC 0 : if (s->curTransactionOwner)
2064 tgl 4792 ECB : {
4793 : /* As in TBLOCK_ABORT, might have a live portal to zap */
2064 tgl 4794 UIC 0 : AtSubAbort_Portals(s->subTransactionId,
4795 0 : s->parent->subTransactionId,
4796 : s->curTransactionOwner,
4797 0 : s->parent->curTransactionOwner);
2064 tgl 4798 EUB : }
6856 tgl 4799 UIC 0 : CleanupSubTransaction();
6797 bruce 4800 0 : s = CurrentTransactionState; /* changed by pop */
6856 tgl 4801 0 : break;
4802 : }
6856 tgl 4803 GIC 11758 : } while (s->blockState != TBLOCK_DEFAULT);
8720 bruce 4804 EUB :
6856 tgl 4805 : /* Should be out of all subxacts now */
6856 tgl 4806 GBC 11758 : Assert(s->parent == NULL);
2064 tgl 4807 EUB :
4808 : /* If we didn't actually have anything to do, revert to TopMemoryContext */
2064 tgl 4809 GBC 11758 : AtCleanup_Memory();
8951 tgl 4810 GIC 11758 : }
4811 :
4812 : /*
7288 tgl 4813 EUB : * IsTransactionBlock --- are we within a transaction block?
4814 : */
4815 : bool
8202 tgl 4816 GBC 346442 : IsTransactionBlock(void)
9770 scrappy 4817 EUB : {
9345 bruce 4818 GIC 346442 : TransactionState s = CurrentTransactionState;
9345 bruce 4819 EUB :
6943 bruce 4820 GIC 346442 : if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
7288 tgl 4821 GBC 279465 : return false;
9345 bruce 4822 EUB :
7288 tgl 4823 GBC 66977 : return true;
4824 : }
7288 tgl 4825 ECB :
4826 : /*
4827 : * IsTransactionOrTransactionBlock --- are we within either a transaction
6797 bruce 4828 : * or a transaction block? (The backend is only really "idle" when this
4829 : * returns false.)
4830 : *
7115 tgl 4831 : * This should match up with IsTransactionBlock and IsTransactionState.
4832 : */
4833 : bool
7115 tgl 4834 GIC 888573 : IsTransactionOrTransactionBlock(void)
4835 : {
4836 888573 : TransactionState s = CurrentTransactionState;
4837 :
6943 bruce 4838 CBC 888573 : if (s->blockState == TBLOCK_DEFAULT)
7115 tgl 4839 GIC 831389 : return false;
7115 tgl 4840 ECB :
7115 tgl 4841 GIC 57184 : return true;
7115 tgl 4842 ECB : }
4843 :
4844 : /*
7288 4845 : * TransactionBlockStatusCode - return status code to send in ReadyForQuery
4846 : */
4847 : char
7288 tgl 4848 GIC 250115 : TransactionBlockStatusCode(void)
4849 : {
4850 250115 : TransactionState s = CurrentTransactionState;
4851 :
4852 250115 : switch (s->blockState)
4853 : {
4854 193701 : case TBLOCK_DEFAULT:
4855 : case TBLOCK_STARTED:
7288 tgl 4856 CBC 193701 : return 'I'; /* idle --- not in transaction */
7288 tgl 4857 GIC 55606 : case TBLOCK_BEGIN:
6779 tgl 4858 ECB : case TBLOCK_SUBBEGIN:
4859 : case TBLOCK_INPROGRESS:
2040 4860 : case TBLOCK_IMPLICIT_INPROGRESS:
2901 rhaas 4861 : case TBLOCK_PARALLEL_INPROGRESS:
4862 : case TBLOCK_SUBINPROGRESS:
6779 tgl 4863 : case TBLOCK_END:
4864 : case TBLOCK_SUBRELEASE:
4865 : case TBLOCK_SUBCOMMIT:
4866 : case TBLOCK_PREPARE:
7288 tgl 4867 GIC 55606 : return 'T'; /* in transaction */
4868 808 : case TBLOCK_ABORT:
4869 : case TBLOCK_SUBABORT:
6779 tgl 4870 ECB : case TBLOCK_ABORT_END:
4871 : case TBLOCK_SUBABORT_END:
4872 : case TBLOCK_ABORT_PENDING:
4873 : case TBLOCK_SUBABORT_PENDING:
4874 : case TBLOCK_SUBRESTART:
4875 : case TBLOCK_SUBABORT_RESTART:
7288 tgl 4876 CBC 808 : return 'E'; /* in failed transaction */
4877 : }
7288 tgl 4878 ECB :
4879 : /* should never get here */
6856 tgl 4880 UIC 0 : elog(FATAL, "invalid transaction block state: %s",
4881 : BlockStateAsString(s->blockState));
4882 : return 0; /* keep compiler quiet */
4883 : }
4884 :
4885 : /*
4886 : * IsSubTransaction
4887 : */
4888 : bool
6856 tgl 4889 CBC 824995 : IsSubTransaction(void)
6856 tgl 4890 ECB : {
6856 tgl 4891 GIC 824995 : TransactionState s = CurrentTransactionState;
4892 :
6825 4893 824995 : if (s->nestingLevel >= 2)
4894 489 : return true;
4895 :
4896 824506 : return false;
4897 : }
6856 tgl 4898 ECB :
4899 : /*
4900 : * StartSubTransaction
4901 : *
6779 tgl 4902 EUB : * If you're wondering why this is separate from PushTransaction: it's because
4903 : * we can't conveniently do this stuff right inside DefineSavepoint. The
4904 : * SAVEPOINT utility command will be executed inside a Portal, and if we
4905 : * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
4906 : * the Portal will undo those settings. So we make DefineSavepoint just
4907 : * push a dummy transaction block, and when control returns to the main
4908 : * idle loop, CommitTransactionCommand will be called, and we'll come here
4909 : * to finish starting the subtransaction.
4910 : */
6856 tgl 4911 ECB : static void
6856 tgl 4912 GIC 8783 : StartSubTransaction(void)
6856 tgl 4913 ECB : {
6856 tgl 4914 GIC 8783 : TransactionState s = CurrentTransactionState;
6856 tgl 4915 ECB :
6856 tgl 4916 CBC 8783 : if (s->state != TRANS_DEFAULT)
6829 tgl 4917 UIC 0 : elog(WARNING, "StartSubTransaction while in %s state",
6829 tgl 4918 ECB : TransStateAsString(s->state));
4919 :
6856 tgl 4920 GIC 8783 : s->state = TRANS_START;
4921 :
4922 : /*
4923 : * Initialize subsystems for new subtransaction
4924 : *
4925 : * must initialize resource-management stuff first
4926 : */
6840 4927 8783 : AtSubStart_Memory();
4928 8783 : AtSubStart_ResourceOwner();
6785 4929 8783 : AfterTriggerBeginSubXact();
4930 :
6856 4931 8783 : s->state = TRANS_INPROGRESS;
4932 :
4933 : /*
6797 bruce 4934 ECB : * Call start-of-subxact callbacks
4935 : */
6779 tgl 4936 CBC 8783 : CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
6779 tgl 4937 GIC 8783 : s->parent->subTransactionId);
6825 tgl 4938 ECB :
6856 tgl 4939 GBC 8783 : ShowTransactionState("StartSubTransaction");
6856 tgl 4940 GIC 8783 : }
4941 :
6856 tgl 4942 ECB : /*
4943 : * CommitSubTransaction
4944 : *
4945 : * The caller has to make sure to always reassign CurrentTransactionState
4946 : * if it has a local pointer to it after calling this function.
4947 : */
4948 : static void
4232 simon 4949 CBC 4315 : CommitSubTransaction(void)
6856 tgl 4950 ECB : {
6856 tgl 4951 CBC 4315 : TransactionState s = CurrentTransactionState;
4952 :
4953 4315 : ShowTransactionState("CommitSubTransaction");
4954 :
6856 tgl 4955 GIC 4315 : if (s->state != TRANS_INPROGRESS)
6829 tgl 4956 UIC 0 : elog(WARNING, "CommitSubTransaction while in %s state",
4957 : TransStateAsString(s->state));
6856 tgl 4958 ECB :
3706 4959 : /* Pre-commit processing goes here */
4960 :
3706 tgl 4961 CBC 4315 : CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId,
4962 4315 : s->parent->subTransactionId);
4963 :
4964 : /* If in parallel mode, clean up workers and exit parallel mode. */
2901 rhaas 4965 GIC 4315 : if (IsInParallelMode())
4966 : {
2901 rhaas 4967 UIC 0 : AtEOSubXact_Parallel(true, s->subTransactionId);
4968 0 : s->parallelModeLevel = 0;
4969 : }
4970 :
3706 tgl 4971 ECB : /* Do the actual "commit", such as it is */
6856 tgl 4972 GIC 4315 : s->state = TRANS_COMMIT;
6856 tgl 4973 ECB :
4974 : /* Must CCI to ensure commands of subtransaction are seen as done */
6856 tgl 4975 CBC 4315 : CommandCounterIncrement();
4976 :
5050 bruce 4977 ECB : /*
3260 bruce 4978 EUB : * Prior to 8.4 we marked subcommit in clog at this point. We now only
4979 : * perform that step, if required, as part of the atomic update of the
4980 : * whole transaction tree at top level commit or abort.
4981 : */
4982 :
6856 tgl 4983 ECB : /* Post-commit cleanup */
1473 tmunro 4984 CBC 4315 : if (FullTransactionIdIsValid(s->fullTransactionId))
5695 tgl 4985 GIC 2804 : AtSubCommit_childXids();
6785 4986 4315 : AfterTriggerEndSubXact(true);
6779 tgl 4987 CBC 4315 : AtSubCommit_Portals(s->subTransactionId,
6779 tgl 4988 GIC 4315 : s->parent->subTransactionId,
555 tgl 4989 GBC 4315 : s->parent->nestingLevel,
6825 4990 4315 : s->parent->curTransactionOwner);
6779 tgl 4991 GIC 4315 : AtEOSubXact_LargeObject(true, s->subTransactionId,
4992 4315 : s->parent->subTransactionId);
6825 4993 4315 : AtSubCommit_Notify();
6825 tgl 4994 ECB :
6779 tgl 4995 GIC 4315 : CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
4996 4315 : s->parent->subTransactionId);
6829 tgl 4997 ECB :
6840 tgl 4998 GIC 4315 : ResourceOwnerRelease(s->curTransactionOwner,
4999 : RESOURCE_RELEASE_BEFORE_LOCKS,
5000 : true, false);
6779 5001 4315 : AtEOSubXact_RelationCache(true, s->subTransactionId,
5002 4315 : s->parent->subTransactionId);
6825 5003 4315 : AtEOSubXact_Inval(true);
6789 5004 4315 : AtSubCommit_smgr();
5005 :
6779 tgl 5006 ECB : /*
5007 : * The only lock we actually release here is the subtransaction XID lock.
5008 : */
6779 tgl 5009 CBC 4315 : CurrentResourceOwner = s->curTransactionOwner;
1473 tmunro 5010 4315 : if (FullTransactionIdIsValid(s->fullTransactionId))
5011 2804 : XactLockTableDelete(XidFromFullTransactionId(s->fullTransactionId));
6779 tgl 5012 ECB :
4282 simon 5013 : /*
5014 : * Other locks should get transferred to their parent resource owner.
5015 : */
6801 tgl 5016 GIC 4315 : ResourceOwnerRelease(s->curTransactionOwner,
6801 tgl 5017 ECB : RESOURCE_RELEASE_LOCKS,
4232 simon 5018 : true, false);
6840 tgl 5019 GIC 4315 : ResourceOwnerRelease(s->curTransactionOwner,
6840 tgl 5020 ECB : RESOURCE_RELEASE_AFTER_LOCKS,
5021 : true, false);
5022 :
5697 tgl 5023 CBC 4315 : AtEOXact_GUC(true, s->gucNestLevel);
6779 5024 4315 : AtEOSubXact_SPI(true, s->subTransactionId);
5025 4315 : AtEOSubXact_on_commit_actions(true, s->subTransactionId,
5026 4315 : s->parent->subTransactionId);
6779 tgl 5027 GIC 4315 : AtEOSubXact_Namespace(true, s->subTransactionId,
5028 4315 : s->parent->subTransactionId);
5029 4315 : AtEOSubXact_Files(true, s->subTransactionId,
5030 4315 : s->parent->subTransactionId);
5827 tgl 5031 CBC 4315 : AtEOSubXact_HashTables(true, s->nestingLevel);
5796 5032 4315 : AtEOSubXact_PgStat(true, s->nestingLevel);
5445 alvherre 5033 4315 : AtSubCommit_Snapshot(s->nestingLevel);
5034 :
5035 : /*
5036 : * We need to restore the upper transaction's read-only state, in case the
5037 : * upper is read-write while the child is read-only; GUC will incorrectly
6385 bruce 5038 ECB : * think it should leave the child state in place.
5039 : */
6829 tgl 5040 GIC 4315 : XactReadOnly = s->prevXactReadOnly;
6829 tgl 5041 ECB :
6840 tgl 5042 GIC 4315 : CurrentResourceOwner = s->parent->curTransactionOwner;
5043 4315 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
6801 5044 4315 : ResourceOwnerDelete(s->curTransactionOwner);
6840 tgl 5045 CBC 4315 : s->curTransactionOwner = NULL;
6840 tgl 5046 ECB :
6856 tgl 5047 CBC 4315 : AtSubCommit_Memory();
6856 tgl 5048 ECB :
6856 tgl 5049 CBC 4315 : s->state = TRANS_DEFAULT;
6779 tgl 5050 ECB :
6779 tgl 5051 CBC 4315 : PopTransaction();
6856 5052 4315 : }
6856 tgl 5053 ECB :
5054 : /*
5055 : * AbortSubTransaction
5056 : */
5057 : static void
6856 tgl 5058 GIC 4468 : AbortSubTransaction(void)
5059 : {
5060 4468 : TransactionState s = CurrentTransactionState;
5061 :
5981 tgl 5062 ECB : /* Prevent cancel/die interrupt while cleaning up */
6856 tgl 5063 GIC 4468 : HOLD_INTERRUPTS();
6856 tgl 5064 ECB :
5981 5065 : /* Make sure we have a valid memory context and resource owner */
5981 tgl 5066 CBC 4468 : AtSubAbort_Memory();
5067 4468 : AtSubAbort_ResourceOwner();
5068 :
6856 tgl 5069 ECB : /*
5070 : * Release any LW locks we might be holding as quickly as possible.
5071 : * (Regular locks, however, must be held till we finish aborting.)
5072 : * Releasing LW locks is critical since we might try to grab them again
6385 bruce 5073 : * while cleaning up!
6856 tgl 5074 : *
5075 : * FIXME This may be incorrect --- Are there some locks we should keep?
5076 : * Buffer locks, for example? I don't think so but I'm not sure.
5077 : */
6856 tgl 5078 GIC 4468 : LWLockReleaseAll();
5079 :
2586 rhaas 5080 CBC 4468 : pgstat_report_wait_end();
2586 rhaas 5081 GIC 4468 : pgstat_progress_end_command();
6856 tgl 5082 4468 : UnlockBuffers();
5083 :
3062 heikki.linnakangas 5084 ECB : /* Reset WAL record construction state */
3062 heikki.linnakangas 5085 GIC 4468 : XLogResetInsertion();
5086 :
1935 rhaas 5087 ECB : /* Cancel condition variable sleep */
1935 rhaas 5088 CBC 4468 : ConditionVariableCancelSleep();
5089 :
5090 : /*
5091 : * Also clean up any open wait for lock, since the lock manager will choke
5092 : * if we try to wait for another lock before doing this.
5093 : */
4008 rhaas 5094 GIC 4468 : LockErrorCleanup();
5095 :
5096 : /*
5097 : * If any timeout events are still active, make sure the timeout interrupt
5098 : * is scheduled. This covers possible loss of a timeout interrupt due to
3418 tgl 5099 ECB : * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
5100 : * We delay this till after LockErrorCleanup so that we don't uselessly
5101 : * reschedule lock or deadlock check timeouts.
5102 : */
3418 tgl 5103 CBC 4468 : reschedule_timeouts();
5104 :
5105 : /*
3418 tgl 5106 ECB : * Re-enable signals, in case we got here by longjmp'ing out of a signal
5107 : * handler. We do this fairly early in the sequence so that the timeout
5108 : * infrastructure will be functional if needed while aborting.
5109 : */
65 tmunro 5110 GNC 4468 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
5111 :
5112 : /*
5113 : * check the current transaction state
5114 : */
5981 tgl 5115 CBC 4468 : ShowTransactionState("AbortSubTransaction");
5116 :
5981 tgl 5117 GIC 4468 : if (s->state != TRANS_INPROGRESS)
5981 tgl 5118 UIC 0 : elog(WARNING, "AbortSubTransaction while in %s state",
5119 : TransStateAsString(s->state));
5120 :
5981 tgl 5121 GIC 4468 : s->state = TRANS_ABORT;
5122 :
5123 : /*
5050 bruce 5124 ECB : * Reset user ID which might have been changed transiently. (See notes in
5125 : * AbortTransaction.)
5126 : */
4869 tgl 5127 GIC 4468 : SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
5128 :
5129 : /* Forget about any active REINDEX. */
1083 5130 4468 : ResetReindexState(s->nestingLevel);
1083 tgl 5131 ECB :
5132 : /* Reset logical streaming state. */
974 akapila 5133 GIC 4468 : ResetLogicalStreamingState();
5134 :
5135 : /*
538 michael 5136 ECB : * No need for SnapBuildResetExportedSnapshotState() here, snapshot
5137 : * exports are not supported in subtransactions.
5138 : */
538 michael 5139 EUB :
5140 : /* Exit from parallel mode, if necessary. */
2901 rhaas 5141 GIC 4468 : if (IsInParallelMode())
2901 rhaas 5142 ECB : {
2901 rhaas 5143 GIC 3 : AtEOSubXact_Parallel(false, s->subTransactionId);
5144 3 : s->parallelModeLevel = 0;
5145 : }
5146 :
5147 : /*
6385 bruce 5148 ECB : * We can skip all this stuff if the subxact failed before creating a
5149 : * ResourceOwner...
5150 : */
6779 tgl 5151 CBC 4468 : if (s->curTransactionOwner)
5152 : {
6779 tgl 5153 GIC 4468 : AfterTriggerEndSubXact(false);
6779 tgl 5154 CBC 4468 : AtSubAbort_Portals(s->subTransactionId,
6779 tgl 5155 GIC 4468 : s->parent->subTransactionId,
5156 : s->curTransactionOwner,
5157 4468 : s->parent->curTransactionOwner);
5158 4468 : AtEOSubXact_LargeObject(false, s->subTransactionId,
5159 4468 : s->parent->subTransactionId);
5160 4468 : AtSubAbort_Notify();
5161 :
2214 rhaas 5162 ECB : /* Advertise the fact that we aborted in pg_xact. */
5692 tgl 5163 GIC 4468 : (void) RecordTransactionAbort(true);
5695 tgl 5164 ECB :
5165 : /* Post-abort cleanup */
1473 tmunro 5166 GIC 4468 : if (FullTransactionIdIsValid(s->fullTransactionId))
6779 tgl 5167 610 : AtSubAbort_childXids();
5168 :
5169 4468 : CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
5170 4468 : s->parent->subTransactionId);
5171 :
6779 tgl 5172 CBC 4468 : ResourceOwnerRelease(s->curTransactionOwner,
5173 : RESOURCE_RELEASE_BEFORE_LOCKS,
6779 tgl 5174 ECB : false, false);
6779 tgl 5175 CBC 4468 : AtEOSubXact_RelationCache(false, s->subTransactionId,
5176 4468 : s->parent->subTransactionId);
6779 tgl 5177 GIC 4468 : AtEOSubXact_Inval(false);
6779 tgl 5178 CBC 4468 : ResourceOwnerRelease(s->curTransactionOwner,
6779 tgl 5179 ECB : RESOURCE_RELEASE_LOCKS,
5180 : false, false);
6779 tgl 5181 CBC 4468 : ResourceOwnerRelease(s->curTransactionOwner,
5182 : RESOURCE_RELEASE_AFTER_LOCKS,
5183 : false, false);
3951 rhaas 5184 4468 : AtSubAbort_smgr();
5185 :
5697 tgl 5186 GIC 4468 : AtEOXact_GUC(false, s->gucNestLevel);
6779 tgl 5187 CBC 4468 : AtEOSubXact_SPI(false, s->subTransactionId);
5188 4468 : AtEOSubXact_on_commit_actions(false, s->subTransactionId,
6779 tgl 5189 GIC 4468 : s->parent->subTransactionId);
6779 tgl 5190 CBC 4468 : AtEOSubXact_Namespace(false, s->subTransactionId,
5191 4468 : s->parent->subTransactionId);
6779 tgl 5192 GIC 4468 : AtEOSubXact_Files(false, s->subTransactionId,
6779 tgl 5193 CBC 4468 : s->parent->subTransactionId);
5827 tgl 5194 GIC 4468 : AtEOSubXact_HashTables(false, s->nestingLevel);
5796 5195 4468 : AtEOSubXact_PgStat(false, s->nestingLevel);
5445 alvherre 5196 CBC 4468 : AtSubAbort_Snapshot(s->nestingLevel);
6779 tgl 5197 ECB : }
6856 5198 :
6829 5199 : /*
5200 : * Restore the upper transaction's read-only state, too. This should be
5201 : * redundant with GUC's cleanup but we may as well do it for consistency
6385 bruce 5202 : * with the commit case.
5203 : */
6829 tgl 5204 GIC 4468 : XactReadOnly = s->prevXactReadOnly;
6829 tgl 5205 ECB :
6856 tgl 5206 GIC 4468 : RESUME_INTERRUPTS();
6856 tgl 5207 CBC 4468 : }
6856 tgl 5208 ECB :
5209 : /*
5210 : * CleanupSubTransaction
6779 5211 : *
5212 : * The caller has to make sure to always reassign CurrentTransactionState
5213 : * if it has a local pointer to it after calling this function.
6856 5214 : */
5215 : static void
6856 tgl 5216 CBC 4468 : CleanupSubTransaction(void)
6856 tgl 5217 ECB : {
6856 tgl 5218 GIC 4468 : TransactionState s = CurrentTransactionState;
5219 :
5220 4468 : ShowTransactionState("CleanupSubTransaction");
5221 :
5222 4468 : if (s->state != TRANS_ABORT)
6829 tgl 5223 UIC 0 : elog(WARNING, "CleanupSubTransaction while in %s state",
5224 : TransStateAsString(s->state));
6856 tgl 5225 ECB :
6779 tgl 5226 GIC 4468 : AtSubCleanup_Portals(s->subTransactionId);
6840 tgl 5227 ECB :
6840 tgl 5228 CBC 4468 : CurrentResourceOwner = s->parent->curTransactionOwner;
6840 tgl 5229 GIC 4468 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
6779 5230 4468 : if (s->curTransactionOwner)
5231 4468 : ResourceOwnerDelete(s->curTransactionOwner);
6840 5232 4468 : s->curTransactionOwner = NULL;
5233 :
6856 5234 4468 : AtSubCleanup_Memory();
5235 :
5236 4468 : s->state = TRANS_DEFAULT;
6856 tgl 5237 ECB :
6779 tgl 5238 GIC 4468 : PopTransaction();
6856 tgl 5239 CBC 4468 : }
5240 :
6856 tgl 5241 ECB : /*
5242 : * PushTransaction
6779 5243 : * Create transaction state stack entry for a subtransaction
6830 tgl 5244 EUB : *
5245 : * The caller has to make sure to always reassign CurrentTransactionState
5246 : * if it has a local pointer to it after calling this function.
6856 tgl 5247 ECB : */
5248 : static void
6856 tgl 5249 CBC 8783 : PushTransaction(void)
6856 tgl 5250 ECB : {
6797 bruce 5251 CBC 8783 : TransactionState p = CurrentTransactionState;
6797 bruce 5252 ECB : TransactionState s;
6856 tgl 5253 :
5254 : /*
5255 : * We keep subtransaction state nodes in TopTransactionContext.
5256 : */
5257 : s = (TransactionState)
6856 tgl 5258 GIC 8783 : MemoryContextAllocZero(TopTransactionContext,
6856 tgl 5259 ECB : sizeof(TransactionStateData));
6385 bruce 5260 :
5261 : /*
5262 : * Assign a subtransaction ID, watching out for counter wraparound.
5263 : */
6779 tgl 5264 GIC 8783 : currentSubTransactionId += 1;
5265 8783 : if (currentSubTransactionId == InvalidSubTransactionId)
5266 : {
6779 tgl 5267 UIC 0 : currentSubTransactionId -= 1;
5268 0 : pfree(s);
5269 0 : ereport(ERROR,
6779 tgl 5270 ECB : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5271 : errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
5272 : }
5273 :
5274 : /*
5275 : * We can now stack a minimally valid subtransaction without fear of
5276 : * failure.
5277 : */
1473 tmunro 5278 GIC 8783 : s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
6779 tgl 5279 CBC 8783 : s->subTransactionId = currentSubTransactionId;
6856 tgl 5280 GIC 8783 : s->parent = p;
5281 8783 : s->nestingLevel = p->nestingLevel + 1;
5697 5282 8783 : s->gucNestLevel = NewGUCNestLevel();
6830 5283 8783 : s->savepointLevel = p->savepointLevel;
6856 5284 8783 : s->state = TRANS_DEFAULT;
6856 tgl 5285 CBC 8783 : s->blockState = TBLOCK_SUBBEGIN;
4869 5286 8783 : GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
6779 tgl 5287 GIC 8783 : s->prevXactReadOnly = XactReadOnly;
2901 rhaas 5288 GBC 8783 : s->parallelModeLevel = 0;
523 akapila 5289 8783 : s->topXidLogged = false;
6856 tgl 5290 EUB :
6779 tgl 5291 GIC 8783 : CurrentTransactionState = s;
5292 :
5293 : /*
5294 : * AbortSubTransaction and CleanupSubTransaction have to be able to cope
5295 : * with the subtransaction from here on out; in particular they should not
5296 : * assume that it necessarily has a transaction context, resource owner,
5297 : * or XID.
5298 : */
6856 tgl 5299 CBC 8783 : }
6856 tgl 5300 ECB :
5301 : /*
5302 : * PopTransaction
5303 : * Pop back to parent transaction state
6830 5304 : *
5305 : * The caller has to make sure to always reassign CurrentTransactionState
5306 : * if it has a local pointer to it after calling this function.
6856 5307 : */
5308 : static void
6856 tgl 5309 CBC 8783 : PopTransaction(void)
6856 tgl 5310 ECB : {
6856 tgl 5311 GIC 8783 : TransactionState s = CurrentTransactionState;
6856 tgl 5312 ECB :
6856 tgl 5313 GIC 8783 : if (s->state != TRANS_DEFAULT)
6829 tgl 5314 UIC 0 : elog(WARNING, "PopTransaction while in %s state",
5315 : TransStateAsString(s->state));
5316 :
6856 tgl 5317 GIC 8783 : if (s->parent == NULL)
6856 tgl 5318 UIC 0 : elog(FATAL, "PopTransaction with no parent");
5319 :
6856 tgl 5320 CBC 8783 : CurrentTransactionState = s->parent;
5321 :
5322 : /* Let's just make sure CurTransactionContext is good */
6856 tgl 5323 GIC 8783 : CurTransactionContext = s->parent->curTransactionContext;
5324 8783 : MemoryContextSwitchTo(CurTransactionContext);
5325 :
5326 : /* Ditto for ResourceOwner links */
6840 5327 8783 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5328 8783 : CurrentResourceOwner = s->parent->curTransactionOwner;
5329 :
6856 tgl 5330 ECB : /* Free the old child structure */
6830 tgl 5331 GIC 8783 : if (s->name)
6830 tgl 5332 CBC 1817 : pfree(s->name);
6856 tgl 5333 GIC 8783 : pfree(s);
6856 tgl 5334 CBC 8783 : }
6856 tgl 5335 EUB :
5336 : /*
5337 : * EstimateTransactionStateSpace
2901 rhaas 5338 ECB : * Estimate the amount of space that will be needed by
2901 rhaas 5339 EUB : * SerializeTransactionState. It would be OK to overestimate slightly,
5340 : * but it's simple for us to work out the precise value, so we do.
2901 rhaas 5341 ECB : */
5342 : Size
2901 rhaas 5343 GIC 403 : EstimateTransactionStateSpace(void)
2901 rhaas 5344 ECB : {
5345 : TransactionState s;
1473 tmunro 5346 GIC 403 : Size nxids = 0;
5347 403 : Size size = SerializedTransactionStateHeaderSize;
2901 rhaas 5348 ECB :
2901 rhaas 5349 CBC 2000 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5350 : {
1473 tmunro 5351 GIC 1597 : if (FullTransactionIdIsValid(s->fullTransactionId))
2901 rhaas 5352 CBC 893 : nxids = add_size(nxids, 1);
5353 1597 : nxids = add_size(nxids, s->nChildXids);
2901 rhaas 5354 ECB : }
5355 :
1458 tmunro 5356 GIC 403 : return add_size(size, mul_size(sizeof(TransactionId), nxids));
5357 : }
5358 :
5359 : /*
5360 : * SerializeTransactionState
5361 : * Write out relevant details of our transaction state that will be
5362 : * needed by a parallel worker.
5363 : *
2901 rhaas 5364 ECB : * We need to save and restore XactDeferrable, XactIsoLevel, and the XIDs
5365 : * associated with this transaction. These are serialized into a
5366 : * caller-supplied buffer big enough to hold the number of bytes reported by
1473 tmunro 5367 : * EstimateTransactionStateSpace(). We emit the XIDs in sorted order for the
5368 : * convenience of the receiving process.
5369 : */
2901 rhaas 5370 : void
2901 rhaas 5371 GIC 403 : SerializeTransactionState(Size maxsize, char *start_address)
2901 rhaas 5372 ECB : {
5373 : TransactionState s;
2878 bruce 5374 CBC 403 : Size nxids = 0;
2878 bruce 5375 GIC 403 : Size i = 0;
5376 : TransactionId *workspace;
1473 tmunro 5377 ECB : SerializedTransactionState *result;
5378 :
1473 tmunro 5379 GIC 403 : result = (SerializedTransactionState *) start_address;
5380 :
5381 403 : result->xactIsoLevel = XactIsoLevel;
5382 403 : result->xactDeferrable = XactDeferrable;
5383 403 : result->topFullTransactionId = XactTopFullTransactionId;
5384 403 : result->currentFullTransactionId =
5385 403 : CurrentTransactionState->fullTransactionId;
5386 403 : result->currentCommandId = currentCommandId;
5387 :
5388 : /*
5389 : * If we're running in a parallel worker and launching a parallel worker
5390 : * of our own, we can just pass along the information that was passed to
5391 : * us.
2901 rhaas 5392 ECB : */
2901 rhaas 5393 GIC 403 : if (nParallelCurrentXids > 0)
5394 : {
1473 tmunro 5395 LBC 0 : result->nParallelCurrentXids = nParallelCurrentXids;
5396 0 : memcpy(&result->parallelCurrentXids[0], ParallelCurrentXids,
5397 : nParallelCurrentXids * sizeof(TransactionId));
2901 rhaas 5398 UIC 0 : return;
5399 : }
2901 rhaas 5400 ECB :
5401 : /*
2878 bruce 5402 : * OK, we need to generate a sorted list of XIDs that our workers should
5403 : * view as current. First, figure out how many there are.
2901 rhaas 5404 : */
2901 rhaas 5405 CBC 2000 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
2901 rhaas 5406 ECB : {
1473 tmunro 5407 CBC 1597 : if (FullTransactionIdIsValid(s->fullTransactionId))
2901 rhaas 5408 GIC 893 : nxids = add_size(nxids, 1);
5409 1597 : nxids = add_size(nxids, s->nChildXids);
5410 : }
1473 tmunro 5411 403 : Assert(SerializedTransactionStateHeaderSize + nxids * sizeof(TransactionId)
5412 : <= maxsize);
5413 :
2901 rhaas 5414 ECB : /* Copy them to our scratch space. */
2901 rhaas 5415 GIC 403 : workspace = palloc(nxids * sizeof(TransactionId));
2901 rhaas 5416 GBC 2000 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
2901 rhaas 5417 EUB : {
1473 tmunro 5418 GIC 1597 : if (FullTransactionIdIsValid(s->fullTransactionId))
1473 tmunro 5419 GBC 893 : workspace[i++] = XidFromFullTransactionId(s->fullTransactionId);
402 tgl 5420 GIC 1597 : if (s->nChildXids > 0)
402 tgl 5421 UIC 0 : memcpy(&workspace[i], s->childXids,
5422 0 : s->nChildXids * sizeof(TransactionId));
2901 rhaas 5423 GIC 1597 : i += s->nChildXids;
5424 : }
5425 403 : Assert(i == nxids);
2901 rhaas 5426 ECB :
5427 : /* Sort them. */
2901 rhaas 5428 CBC 403 : qsort(workspace, nxids, sizeof(TransactionId), xidComparator);
2901 rhaas 5429 ECB :
5430 : /* Copy data into output area. */
1473 tmunro 5431 GIC 403 : result->nParallelCurrentXids = nxids;
1473 tmunro 5432 CBC 403 : memcpy(&result->parallelCurrentXids[0], workspace,
5433 : nxids * sizeof(TransactionId));
5434 : }
5435 :
2901 rhaas 5436 ECB : /*
5437 : * StartParallelWorkerTransaction
5438 : * Start a parallel worker transaction, restoring the relevant
5439 : * transaction state serialized by SerializeTransactionState.
5440 : */
5441 : void
2901 rhaas 5442 GBC 1298 : StartParallelWorkerTransaction(char *tstatespace)
2901 rhaas 5443 EUB : {
1473 tmunro 5444 ECB : SerializedTransactionState *tstate;
5445 :
2901 rhaas 5446 CBC 1298 : Assert(CurrentTransactionState->blockState == TBLOCK_DEFAULT);
2901 rhaas 5447 GIC 1298 : StartTransaction();
5448 :
1473 tmunro 5449 CBC 1298 : tstate = (SerializedTransactionState *) tstatespace;
1473 tmunro 5450 GIC 1298 : XactIsoLevel = tstate->xactIsoLevel;
5451 1298 : XactDeferrable = tstate->xactDeferrable;
1473 tmunro 5452 CBC 1298 : XactTopFullTransactionId = tstate->topFullTransactionId;
5453 1298 : CurrentTransactionState->fullTransactionId =
5454 : tstate->currentFullTransactionId;
1473 tmunro 5455 GIC 1298 : currentCommandId = tstate->currentCommandId;
5456 1298 : nParallelCurrentXids = tstate->nParallelCurrentXids;
5457 1298 : ParallelCurrentXids = &tstate->parallelCurrentXids[0];
5458 :
2901 rhaas 5459 1298 : CurrentTransactionState->blockState = TBLOCK_PARALLEL_INPROGRESS;
5460 1298 : }
5461 :
5462 : /*
2901 rhaas 5463 ECB : * EndParallelWorkerTransaction
5464 : * End a parallel worker transaction.
5465 : */
5466 : void
2901 rhaas 5467 CBC 1295 : EndParallelWorkerTransaction(void)
2901 rhaas 5468 ECB : {
2901 rhaas 5469 GIC 1295 : Assert(CurrentTransactionState->blockState == TBLOCK_PARALLEL_INPROGRESS);
2901 rhaas 5470 CBC 1295 : CommitTransaction();
5471 1295 : CurrentTransactionState->blockState = TBLOCK_DEFAULT;
5472 1295 : }
2901 rhaas 5473 ECB :
6856 tgl 5474 : /*
5475 : * ShowTransactionState
5476 : * Debug support
5477 : */
5478 : static void
6856 tgl 5479 GIC 972988 : ShowTransactionState(const char *str)
6856 tgl 5480 ECB : {
5481 : /* skip work if message will definitely not be printed */
867 tgl 5482 GIC 972988 : if (message_level_is_interesting(DEBUG5))
2334 rhaas 5483 UIC 0 : ShowTransactionStateRec(str, CurrentTransactionState);
6856 tgl 5484 GIC 972988 : }
5485 :
5486 : /*
5487 : * ShowTransactionStateRec
6856 tgl 5488 ECB : * Recursive subroutine for ShowTransactionState
5489 : */
5490 : static void
2334 rhaas 5491 LBC 0 : ShowTransactionStateRec(const char *str, TransactionState s)
6856 tgl 5492 ECB : {
5501 5493 : StringInfoData buf;
5494 :
5501 tgl 5495 UIC 0 : initStringInfo(&buf);
5496 :
5497 0 : if (s->nChildXids > 0)
5498 : {
5499 : int i;
5501 tgl 5500 ECB :
2334 rhaas 5501 UIC 0 : appendStringInfo(&buf, ", children: %u", s->childXids[0]);
5501 tgl 5502 0 : for (i = 1; i < s->nChildXids; i++)
5501 tgl 5503 LBC 0 : appendStringInfo(&buf, " %u", s->childXids[i]);
5501 tgl 5504 EUB : }
5501 tgl 5505 ECB :
6856 tgl 5506 UIC 0 : if (s->parent)
2334 rhaas 5507 0 : ShowTransactionStateRec(str, s->parent);
5508 :
5509 0 : ereport(DEBUG5,
5510 : (errmsg_internal("%s(%d) name: %s; blockState: %s; state: %s, xid/subid/cid: %u/%u/%u%s%s",
5511 : str, s->nestingLevel,
6385 bruce 5512 EUB : PointerIsValid(s->name) ? s->name : "unnamed",
5513 : BlockStateAsString(s->blockState),
5514 : TransStateAsString(s->state),
5515 : (unsigned int) XidFromFullTransactionId(s->fullTransactionId),
6779 tgl 5516 : (unsigned int) s->subTransactionId,
5517 : (unsigned int) currentCommandId,
5609 5518 : currentCommandIdUsed ? " (used)" : "",
5519 : buf.data)));
5520 :
5501 tgl 5521 UIC 0 : pfree(buf.data);
6856 tgl 5522 UBC 0 : }
6856 tgl 5523 EUB :
5524 : /*
5525 : * BlockStateAsString
5526 : * Debug support
5527 : */
5528 : static const char *
6856 tgl 5529 UIC 0 : BlockStateAsString(TBlockState blockState)
6856 tgl 5530 EUB : {
6830 tgl 5531 UIC 0 : switch (blockState)
5532 : {
6856 5533 0 : case TBLOCK_DEFAULT:
5534 0 : return "DEFAULT";
5535 0 : case TBLOCK_STARTED:
5536 0 : return "STARTED";
5537 0 : case TBLOCK_BEGIN:
5538 0 : return "BEGIN";
5539 0 : case TBLOCK_INPROGRESS:
5540 0 : return "INPROGRESS";
2040 5541 0 : case TBLOCK_IMPLICIT_INPROGRESS:
2040 tgl 5542 UBC 0 : return "IMPLICIT_INPROGRESS";
2901 rhaas 5543 0 : case TBLOCK_PARALLEL_INPROGRESS:
2901 rhaas 5544 UIC 0 : return "PARALLEL_INPROGRESS";
6856 tgl 5545 0 : case TBLOCK_END:
5546 0 : return "END";
5547 0 : case TBLOCK_ABORT:
5548 0 : return "ABORT";
6779 5549 0 : case TBLOCK_ABORT_END:
1877 peter_e 5550 UBC 0 : return "ABORT_END";
6779 tgl 5551 UIC 0 : case TBLOCK_ABORT_PENDING:
1877 peter_e 5552 UBC 0 : return "ABORT_PENDING";
6505 tgl 5553 UIC 0 : case TBLOCK_PREPARE:
6505 tgl 5554 UBC 0 : return "PREPARE";
6856 5555 0 : case TBLOCK_SUBBEGIN:
1877 peter_e 5556 0 : return "SUBBEGIN";
6856 tgl 5557 0 : case TBLOCK_SUBINPROGRESS:
1877 peter_e 5558 0 : return "SUBINPROGRESS";
4282 simon 5559 0 : case TBLOCK_SUBRELEASE:
1877 peter_e 5560 0 : return "SUBRELEASE";
4282 simon 5561 0 : case TBLOCK_SUBCOMMIT:
1877 peter_e 5562 0 : return "SUBCOMMIT";
6856 tgl 5563 0 : case TBLOCK_SUBABORT:
1877 peter_e 5564 0 : return "SUBABORT";
6779 tgl 5565 0 : case TBLOCK_SUBABORT_END:
1877 peter_e 5566 0 : return "SUBABORT_END";
6830 tgl 5567 0 : case TBLOCK_SUBABORT_PENDING:
1877 peter_e 5568 0 : return "SUBABORT_PENDING";
6779 tgl 5569 0 : case TBLOCK_SUBRESTART:
1877 peter_e 5570 0 : return "SUBRESTART";
6779 tgl 5571 0 : case TBLOCK_SUBABORT_RESTART:
1877 peter_e 5572 0 : return "SUBABORT_RESTART";
6856 tgl 5573 EUB : }
6856 tgl 5574 UBC 0 : return "UNRECOGNIZED";
6856 tgl 5575 EUB : }
5576 :
5577 : /*
5578 : * TransStateAsString
5579 : * Debug support
5580 : */
5581 : static const char *
6856 tgl 5582 UBC 0 : TransStateAsString(TransState state)
6856 tgl 5583 EUB : {
6830 tgl 5584 UBC 0 : switch (state)
6830 tgl 5585 EUB : {
6856 tgl 5586 UBC 0 : case TRANS_DEFAULT:
5587 0 : return "DEFAULT";
5588 0 : case TRANS_START:
5589 0 : return "START";
6505 5590 0 : case TRANS_INPROGRESS:
1877 peter_e 5591 0 : return "INPROGRESS";
6856 tgl 5592 0 : case TRANS_COMMIT:
5593 0 : return "COMMIT";
6856 tgl 5594 UIC 0 : case TRANS_ABORT:
6856 tgl 5595 UBC 0 : return "ABORT";
6505 tgl 5596 UIC 0 : case TRANS_PREPARE:
5597 0 : return "PREPARE";
5598 : }
6856 5599 0 : return "UNRECOGNIZED";
5600 : }
5601 :
5602 : /*
6856 tgl 5603 EUB : * xactGetCommittedChildren
5604 : *
3260 bruce 5605 : * Gets the list of committed children of the current transaction. The return
5606 : * value is the number of child transactions. *ptr is set to point to an
5501 tgl 5607 : * array of TransactionIds. The array is allocated in TopTransactionContext;
5608 : * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
5609 : * If there are no subxacts, *ptr is set to NULL.
6856 5610 : */
5611 : int
6840 tgl 5612 GBC 468793 : xactGetCommittedChildren(TransactionId **ptr)
6856 tgl 5613 EUB : {
6797 bruce 5614 GBC 468793 : TransactionState s = CurrentTransactionState;
6856 tgl 5615 EUB :
5501 tgl 5616 GBC 468793 : if (s->nChildXids == 0)
6856 5617 468159 : *ptr = NULL;
5501 tgl 5618 EUB : else
5501 tgl 5619 GIC 634 : *ptr = s->childXids;
6856 tgl 5620 EUB :
5501 tgl 5621 GIC 468793 : return s->nChildXids;
5622 : }
5623 :
5624 : /*
5625 : * XLOG support routines
5626 : */
5627 :
5628 :
5629 : /*
5630 : * Log the commit record for a plain or twophase transaction commit.
5631 : *
5632 : * A 2pc commit will be emitted when twophase_xid is valid, a plain one
2947 andres 5633 ECB : * otherwise.
5634 : */
5635 : XLogRecPtr
2947 andres 5636 GIC 293823 : XactLogCommitRecord(TimestampTz commit_time,
2878 bruce 5637 ECB : int nsubxacts, TransactionId *subxacts,
5638 : int nrels, RelFileLocator *rels,
5639 : int ndroppedstats, xl_xact_stats_item *droppedstats,
5640 : int nmsgs, SharedInvalidationMessage *msgs,
5641 : bool relcacheInval,
1838 simon 5642 : int xactflags, TransactionId twophase_xid,
5643 : const char *twophase_gid)
5644 : {
5645 : xl_xact_commit xlrec;
5646 : xl_xact_xinfo xl_xinfo;
5647 : xl_xact_dbinfo xl_dbinfo;
5648 : xl_xact_subxacts xl_subxacts;
5649 : xl_xact_relfilelocators xl_relfilelocators;
5650 : xl_xact_stats_items xl_dropped_stats;
5651 : xl_xact_invals xl_invals;
5652 : xl_xact_twophase xl_twophase;
5653 : xl_xact_origin xl_origin;
5654 : uint8 info;
5655 :
2947 andres 5656 GIC 293823 : Assert(CritSectionCount > 0);
2947 andres 5657 ECB :
2947 andres 5658 GIC 293823 : xl_xinfo.xinfo = 0;
5659 :
5660 : /* decide between a plain and 2pc commit */
5661 293823 : if (!TransactionIdIsValid(twophase_xid))
5662 293498 : info = XLOG_XACT_COMMIT;
5663 : else
5664 325 : info = XLOG_XACT_COMMIT_PREPARED;
5665 :
5666 : /* First figure out and collect all the information needed */
5667 :
5668 293823 : xlrec.xact_time = commit_time;
5669 :
5670 293823 : if (relcacheInval)
5671 21924 : xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
5672 293823 : if (forceSyncCommit)
5673 878 : xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
2209 simon 5674 293823 : if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
5675 100012 : xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
5676 :
2567 rhaas 5677 ECB : /*
5678 : * Check if the caller would like to ask standbys for immediate feedback
5679 : * once this commit is applied.
5680 : */
2567 rhaas 5681 GIC 293823 : if (synchronous_commit >= SYNCHRONOUS_COMMIT_REMOTE_APPLY)
2567 rhaas 5682 LBC 0 : xl_xinfo.xinfo |= XACT_COMPLETION_APPLY_FEEDBACK;
2567 rhaas 5683 ECB :
5684 : /*
2947 andres 5685 : * Relcache invalidations requires information about the current database
5686 : * and so does logical decoding.
5687 : */
2947 andres 5688 GIC 293823 : if (nmsgs > 0 || XLogLogicalInfoActive())
2947 andres 5689 ECB : {
2947 andres 5690 GIC 252963 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
2947 andres 5691 CBC 252963 : xl_dbinfo.dbId = MyDatabaseId;
5692 252963 : xl_dbinfo.tsId = MyDatabaseTableSpace;
2947 andres 5693 ECB : }
5694 :
2947 andres 5695 CBC 293823 : if (nsubxacts > 0)
2947 andres 5696 ECB : {
2947 andres 5697 GIC 540 : xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
5698 540 : xl_subxacts.nsubxacts = nsubxacts;
5699 : }
5700 :
5701 293823 : if (nrels > 0)
2947 andres 5702 ECB : {
277 rhaas 5703 GNC 7396 : xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
5704 7396 : xl_relfilelocators.nrels = nrels;
965 heikki.linnakangas 5705 GIC 7396 : info |= XLR_SPECIAL_REL_UPDATE;
5706 : }
5707 :
368 andres 5708 293823 : if (ndroppedstats > 0)
368 andres 5709 ECB : {
368 andres 5710 GIC 8939 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
368 andres 5711 CBC 8939 : xl_dropped_stats.nitems = ndroppedstats;
368 andres 5712 ECB : }
5713 :
2947 andres 5714 GIC 293823 : if (nmsgs > 0)
5715 : {
2947 andres 5716 CBC 251876 : xl_xinfo.xinfo |= XACT_XINFO_HAS_INVALS;
2947 andres 5717 GIC 251876 : xl_invals.nmsgs = nmsgs;
2947 andres 5718 ECB : }
5719 :
2947 andres 5720 GIC 293823 : if (TransactionIdIsValid(twophase_xid))
5721 : {
2947 andres 5722 CBC 325 : xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
2947 andres 5723 GIC 325 : xl_twophase.xid = twophase_xid;
1838 simon 5724 CBC 325 : Assert(twophase_gid != NULL);
1838 simon 5725 ECB :
1838 simon 5726 CBC 325 : if (XLogLogicalInfoActive())
1838 simon 5727 GIC 49 : xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
5728 : }
2947 andres 5729 ECB :
5730 : /* dump transaction origin information */
2750 alvherre 5731 CBC 293823 : if (replorigin_session_origin != InvalidRepOriginId)
2902 andres 5732 ECB : {
2902 andres 5733 GIC 851 : xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
5734 :
2750 alvherre 5735 CBC 851 : xl_origin.origin_lsn = replorigin_session_origin_lsn;
2750 alvherre 5736 GIC 851 : xl_origin.origin_timestamp = replorigin_session_origin_timestamp;
2902 andres 5737 ECB : }
5738 :
2947 andres 5739 GIC 293823 : if (xl_xinfo.xinfo != 0)
5740 256562 : info |= XLOG_XACT_HAS_INFO;
2947 andres 5741 ECB :
5742 : /* Then include all the collected data into the commit record. */
5743 :
2947 andres 5744 CBC 293823 : XLogBeginInsert();
2947 andres 5745 ECB :
2947 andres 5746 GIC 293823 : XLogRegisterData((char *) (&xlrec), sizeof(xl_xact_commit));
2947 andres 5747 ECB :
2947 andres 5748 CBC 293823 : if (xl_xinfo.xinfo != 0)
2947 andres 5749 GIC 256562 : XLogRegisterData((char *) (&xl_xinfo.xinfo), sizeof(xl_xinfo.xinfo));
5750 :
5751 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
2947 andres 5752 CBC 252963 : XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo));
5753 :
5754 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
5755 : {
5756 540 : XLogRegisterData((char *) (&xl_subxacts),
2947 andres 5757 ECB : MinSizeOfXactSubxacts);
2947 andres 5758 GIC 540 : XLogRegisterData((char *) subxacts,
5759 : nsubxacts * sizeof(TransactionId));
2947 andres 5760 ECB : }
5761 :
277 rhaas 5762 GNC 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
5763 : {
5764 7396 : XLogRegisterData((char *) (&xl_relfilelocators),
5765 : MinSizeOfXactRelfileLocators);
2947 andres 5766 GIC 7396 : XLogRegisterData((char *) rels,
5767 : nrels * sizeof(RelFileLocator));
5768 : }
2947 andres 5769 ECB :
368 andres 5770 CBC 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
5771 : {
5772 8939 : XLogRegisterData((char *) (&xl_dropped_stats),
368 andres 5773 ECB : MinSizeOfXactStatsItems);
368 andres 5774 GIC 8939 : XLogRegisterData((char *) droppedstats,
368 andres 5775 ECB : ndroppedstats * sizeof(xl_xact_stats_item));
5776 : }
5777 :
2947 andres 5778 GIC 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_INVALS)
2947 andres 5779 ECB : {
2947 andres 5780 GIC 251876 : XLogRegisterData((char *) (&xl_invals), MinSizeOfXactInvals);
5781 251876 : XLogRegisterData((char *) msgs,
5782 : nmsgs * sizeof(SharedInvalidationMessage));
2947 andres 5783 ECB : }
5784 :
2947 andres 5785 CBC 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
5786 : {
5787 325 : XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase));
1838 simon 5788 GIC 325 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
1531 peter 5789 49 : XLogRegisterData(unconstify(char *, twophase_gid), strlen(twophase_gid) + 1);
5790 : }
2947 andres 5791 ECB :
2902 andres 5792 GIC 293823 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
2902 andres 5793 CBC 851 : XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
5794 :
2902 andres 5795 ECB : /* we allow filtering by xacts */
2299 andres 5796 GIC 293823 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
5797 :
2947 5798 293823 : return XLogInsert(RM_XACT_ID, info);
2947 andres 5799 ECB : }
5800 :
5801 : /*
5802 : * Log the commit record for a plain or twophase transaction abort.
5803 : *
5804 : * A 2pc abort will be emitted when twophase_xid is valid, a plain one
5805 : * otherwise.
5806 : */
5807 : XLogRecPtr
2947 andres 5808 CBC 4818 : XactLogAbortRecord(TimestampTz abort_time,
2878 bruce 5809 ECB : int nsubxacts, TransactionId *subxacts,
5810 : int nrels, RelFileLocator *rels,
5811 : int ndroppedstats, xl_xact_stats_item *droppedstats,
5812 : int xactflags, TransactionId twophase_xid,
1838 simon 5813 : const char *twophase_gid)
2947 andres 5814 : {
5815 : xl_xact_abort xlrec;
5816 : xl_xact_xinfo xl_xinfo;
2878 bruce 5817 : xl_xact_subxacts xl_subxacts;
5818 : xl_xact_relfilelocators xl_relfilelocators;
368 andres 5819 : xl_xact_stats_items xl_dropped_stats;
5820 : xl_xact_twophase xl_twophase;
5821 : xl_xact_dbinfo xl_dbinfo;
5822 : xl_xact_origin xl_origin;
5823 :
5824 : uint8 info;
5825 :
2947 andres 5826 GIC 4818 : Assert(CritSectionCount > 0);
5827 :
5828 4818 : xl_xinfo.xinfo = 0;
2947 andres 5829 ECB :
5830 : /* decide between a plain and 2pc abort */
2947 andres 5831 GIC 4818 : if (!TransactionIdIsValid(twophase_xid))
5832 4780 : info = XLOG_XACT_ABORT;
5833 : else
5834 38 : info = XLOG_XACT_ABORT_PREPARED;
5835 :
5836 :
5837 : /* First figure out and collect all the information needed */
5838 :
5839 4818 : xlrec.xact_time = abort_time;
5840 :
2209 simon 5841 4818 : if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
5842 1905 : xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
5843 :
2947 andres 5844 4818 : if (nsubxacts > 0)
5845 : {
5846 100 : xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
2947 andres 5847 CBC 100 : xl_subxacts.nsubxacts = nsubxacts;
5848 : }
2947 andres 5849 ECB :
2947 andres 5850 GIC 4818 : if (nrels > 0)
5851 : {
277 rhaas 5852 GNC 697 : xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
5853 697 : xl_relfilelocators.nrels = nrels;
965 heikki.linnakangas 5854 GIC 697 : info |= XLR_SPECIAL_REL_UPDATE;
2947 andres 5855 ECB : }
5856 :
368 andres 5857 GIC 4818 : if (ndroppedstats > 0)
5858 : {
5859 969 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
368 andres 5860 CBC 969 : xl_dropped_stats.nitems = ndroppedstats;
5861 : }
368 andres 5862 ECB :
2947 andres 5863 CBC 4818 : if (TransactionIdIsValid(twophase_xid))
5864 : {
5865 38 : xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
2947 andres 5866 GIC 38 : xl_twophase.xid = twophase_xid;
1838 simon 5867 CBC 38 : Assert(twophase_gid != NULL);
1838 simon 5868 ECB :
1838 simon 5869 GIC 38 : if (XLogLogicalInfoActive())
5870 16 : xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
1838 simon 5871 ECB : }
5872 :
1838 simon 5873 CBC 4818 : if (TransactionIdIsValid(twophase_xid) && XLogLogicalInfoActive())
1838 simon 5874 ECB : {
1838 simon 5875 CBC 16 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
1838 simon 5876 GIC 16 : xl_dbinfo.dbId = MyDatabaseId;
5877 16 : xl_dbinfo.tsId = MyDatabaseTableSpace;
1838 simon 5878 ECB : }
5879 :
762 akapila 5880 : /*
5881 : * Dump transaction origin information. We need this during recovery to
5882 : * update the replication origin progress.
5883 : */
90 akapila 5884 GNC 4818 : if (replorigin_session_origin != InvalidRepOriginId)
1838 simon 5885 ECB : {
1838 simon 5886 CBC 38 : xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
1838 simon 5887 ECB :
1838 simon 5888 GIC 38 : xl_origin.origin_lsn = replorigin_session_origin_lsn;
1838 simon 5889 CBC 38 : xl_origin.origin_timestamp = replorigin_session_origin_timestamp;
2947 andres 5890 ECB : }
5891 :
2947 andres 5892 GIC 4818 : if (xl_xinfo.xinfo != 0)
2947 andres 5893 CBC 2386 : info |= XLOG_XACT_HAS_INFO;
5894 :
2947 andres 5895 ECB : /* Then include all the collected data into the abort record. */
5896 :
2947 andres 5897 CBC 4818 : XLogBeginInsert();
5898 :
2947 andres 5899 GIC 4818 : XLogRegisterData((char *) (&xlrec), MinSizeOfXactAbort);
5900 :
5901 4818 : if (xl_xinfo.xinfo != 0)
5902 2386 : XLogRegisterData((char *) (&xl_xinfo), sizeof(xl_xinfo));
5903 :
1838 simon 5904 CBC 4818 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
1838 simon 5905 GIC 16 : XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo));
1838 simon 5906 ECB :
2947 andres 5907 GIC 4818 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
2947 andres 5908 ECB : {
2947 andres 5909 CBC 100 : XLogRegisterData((char *) (&xl_subxacts),
5910 : MinSizeOfXactSubxacts);
2947 andres 5911 GIC 100 : XLogRegisterData((char *) subxacts,
2947 andres 5912 ECB : nsubxacts * sizeof(TransactionId));
5913 : }
5914 :
277 rhaas 5915 GNC 4818 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
5916 : {
5917 697 : XLogRegisterData((char *) (&xl_relfilelocators),
5918 : MinSizeOfXactRelfileLocators);
2947 andres 5919 CBC 697 : XLogRegisterData((char *) rels,
5920 : nrels * sizeof(RelFileLocator));
2947 andres 5921 ECB : }
5922 :
368 andres 5923 GIC 4818 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
368 andres 5924 ECB : {
368 andres 5925 CBC 969 : XLogRegisterData((char *) (&xl_dropped_stats),
5926 : MinSizeOfXactStatsItems);
5927 969 : XLogRegisterData((char *) droppedstats,
5928 : ndroppedstats * sizeof(xl_xact_stats_item));
368 andres 5929 ECB : }
5930 :
2947 andres 5931 CBC 4818 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
5932 : {
2947 andres 5933 GIC 38 : XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase));
1838 simon 5934 38 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
1531 peter 5935 CBC 16 : XLogRegisterData(unconstify(char *, twophase_gid), strlen(twophase_gid) + 1);
5936 : }
1838 simon 5937 ECB :
1838 simon 5938 GIC 4818 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
1838 simon 5939 CBC 38 : XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
5940 :
5941 : /* Include the replication origin */
90 akapila 5942 GNC 4818 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
2947 andres 5943 ECB :
2947 andres 5944 GIC 4818 : return XLogInsert(RM_XACT_ID, info);
2947 andres 5945 ECB : }
5946 :
4859 simon 5947 : /*
5948 : * Before 9.0 this was a fairly short function, but now it performs many
5949 : * actions for which the order of execution is critical.
5950 : */
6505 tgl 5951 : static void
2947 andres 5952 GIC 18923 : xact_redo_commit(xl_xact_parsed_commit *parsed,
2947 andres 5953 ECB : TransactionId xid,
2902 5954 : XLogRecPtr lsn,
5955 : RepOriginId origin_id)
5956 : {
5957 : TransactionId max_xid;
2878 bruce 5958 : TimestampTz commit_time;
6505 tgl 5959 :
2125 alvherre 5960 GIC 18923 : Assert(TransactionIdIsValid(xid));
5961 :
2947 andres 5962 CBC 18923 : max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
5963 :
971 andres 5964 ECB : /* Make sure nextXid is beyond any XID mentioned in the record. */
1473 tmunro 5965 GIC 18923 : AdvanceNextFullTransactionIdPastXid(max_xid);
5966 :
2569 andres 5967 18923 : Assert(((parsed->xinfo & XACT_XINFO_HAS_ORIGIN) == 0) ==
5968 : (origin_id == InvalidRepOriginId));
5969 :
2902 5970 18923 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
5971 24 : commit_time = parsed->origin_timestamp;
2902 andres 5972 ECB : else
2902 andres 5973 GIC 18899 : commit_time = parsed->xact_time;
5974 :
5975 : /* Set the transaction commit timestamp and metadata */
2947 5976 18923 : TransactionTreeSetCommitTsData(xid, parsed->nsubxacts, parsed->subxacts,
5977 : commit_time, origin_id);
5978 :
4714 simon 5979 18923 : if (standbyState == STANDBY_DISABLED)
4859 simon 5980 ECB : {
5981 : /*
2214 rhaas 5982 : * Mark the transaction committed in pg_xact.
5983 : */
2947 andres 5984 GIC 2153 : TransactionIdCommitTree(xid, parsed->nsubxacts, parsed->subxacts);
4859 simon 5985 ECB : }
5986 : else
5987 : {
5988 : /*
5989 : * If a transaction completion record arrives that has as-yet
4808 tgl 5990 : * unobserved subtransactions then this will not have been fully
5991 : * handled by the call to RecordKnownAssignedTransactionIds() in the
5992 : * main recovery loop in xlog.c. So we need to do bookkeeping again to
5993 : * cover that case. This is confusing and it is easy to think this
5994 : * call is irrelevant, which has happened three times in development
5995 : * already. Leave it in.
4859 simon 5996 : */
4859 simon 5997 GIC 16770 : RecordKnownAssignedTransactionIds(max_xid);
5998 :
4859 simon 5999 ECB : /*
6000 : * Mark the transaction committed in pg_xact. We use async commit
6001 : * protocol during recovery to provide information on database
6002 : * consistency for when users try to set hint bits. It is important
6003 : * that we do not set hint bits until the minRecoveryPoint is past
4790 bruce 6004 : * this commit record. This ensures that if we crash we don't see hint
6005 : * bits set on changes made by transactions that haven't yet
6006 : * recovered. It's unlikely but it's good to be safe.
6007 : */
1165 alvherre 6008 GIC 16770 : TransactionIdAsyncCommitTree(xid, parsed->nsubxacts, parsed->subxacts, lsn);
6009 :
6010 : /*
6011 : * We must mark clog before we update the ProcArray.
6012 : */
6013 16770 : ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
6014 :
6015 : /*
6016 : * Send any cache invalidations attached to the commit. We must
4790 bruce 6017 ECB : * maintain the same order of invalidation then release locks as
6018 : * occurs in CommitTransaction().
6019 : */
1165 alvherre 6020 GIC 16770 : ProcessCommittedInvalidationMessages(parsed->msgs, parsed->nmsgs,
2118 tgl 6021 16770 : XactCompletionRelcacheInitFileInval(parsed->xinfo),
6022 : parsed->dbId, parsed->tsId);
6023 :
6024 : /*
6025 : * Release locks, if any. We do this for both two phase and normal one
6026 : * phase transactions. In effect we are ignoring the prepare phase and
6027 : * just going straight to lock release.
4859 simon 6028 ECB : */
2209 simon 6029 GIC 16770 : if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
1758 6030 8063 : StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
6031 : }
6032 :
2902 andres 6033 CBC 18923 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6034 : {
6035 : /* recover apply progress */
2902 andres 6036 GIC 24 : replorigin_advance(origin_id, parsed->origin_lsn, lsn,
6037 : false /* backward */ , false /* WAL */ );
6038 : }
6039 :
6505 tgl 6040 ECB : /* Make sure files supposed to be dropped are dropped */
2947 andres 6041 CBC 18923 : if (parsed->nrels > 0)
6042 : {
6043 : /*
6044 : * First update minimum recovery point to cover this WAL record. Once
6045 : * a relation is deleted, there's no going back. The buffer manager
6046 : * enforces the WAL-first rule for normal updates to relation files,
6047 : * so that the minimum recovery point is always updated before the
6048 : * corresponding change in the data file is flushed to disk, but we
3772 heikki.linnakangas 6049 ECB : * have to do the same here since we're bypassing the buffer manager.
6050 : *
6051 : * Doing this before deleting the files means that if a deletion fails
6052 : * for some reason, you cannot start up the system even after restart,
6053 : * until you fix the underlying situation so that the deletion will
6054 : * succeed. Alternatively, we could update the minimum recovery point
6055 : * after deletion, but that would leave a small window where the
6056 : * WAL-first rule would be violated.
6057 : */
3772 heikki.linnakangas 6058 GIC 1629 : XLogFlush(lsn);
6059 :
6060 : /* Make sure files supposed to be dropped are dropped */
277 rhaas 6061 GNC 1629 : DropRelationFiles(parsed->xlocators, parsed->nrels, true);
6062 : }
6063 :
368 andres 6064 GIC 18923 : if (parsed->nstats > 0)
6065 : {
6066 : /* see equivalent call for relations above */
6067 2192 : XLogFlush(lsn);
6068 :
6069 2192 : pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
6070 : }
6071 :
6072 : /*
6073 : * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
6074 : * in normal operation. For example, in CREATE DATABASE, we copy all files
6075 : * from the template database, and then commit the transaction. If we
6076 : * crash after all the files have been copied but before the commit, you
6077 : * have files in the data directory without an entry in pg_database. To
3602 bruce 6078 ECB : * minimize the window for that, we use ForceSyncCommit() to rush the
6079 : * commit record to disk as quick as possible. We have the same window
6080 : * during recovery, and forcing an XLogFlush() (which updates
6081 : * minRecoveryPoint during recovery) helps to reduce that problem window,
6082 : * for any user that requested ForceSyncCommit().
6083 : */
2947 andres 6084 CBC 18923 : if (XactCompletionForceSyncCommit(parsed->xinfo))
4859 simon 6085 GIC 39 : XLogFlush(lsn);
6086 :
2567 rhaas 6087 ECB : /*
6088 : * If asked by the primary (because someone is waiting for a synchronous
2495 6089 : * commit = remote_apply), we will need to ask walreceiver to send a reply
6090 : * immediately.
6091 : */
2567 rhaas 6092 GIC 18923 : if (XactCompletionApplyFeedback(parsed->xinfo))
2567 rhaas 6093 UIC 0 : XLogRequestWalReceiverReply();
4303 simon 6094 GIC 18923 : }
6095 :
6096 : /*
6097 : * Be careful with the order of execution, as with xact_redo_commit().
6098 : * The two functions are similar but differ in key places.
6099 : *
6100 : * Note also that an abort can be for a subtransaction and its children,
6101 : * not just for a top level abort. That means we have to consider
6102 : * topxid != xid, whereas in commit we would find topxid == xid always
6103 : * because subtransaction commit is never WAL logged.
4859 simon 6104 ECB : */
6505 tgl 6105 : static void
762 akapila 6106 GIC 1429 : xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid,
6107 : XLogRecPtr lsn, RepOriginId origin_id)
6108 : {
6109 : TransactionId max_xid;
6110 :
2125 alvherre 6111 1429 : Assert(TransactionIdIsValid(xid));
2125 alvherre 6112 ECB :
971 andres 6113 EUB : /* Make sure nextXid is beyond any XID mentioned in the record. */
2947 andres 6114 CBC 1429 : max_xid = TransactionIdLatest(xid,
6115 : parsed->nsubxacts,
2947 andres 6116 GIC 1429 : parsed->subxacts);
1473 tmunro 6117 1429 : AdvanceNextFullTransactionIdPastXid(max_xid);
6118 :
4714 simon 6119 1429 : if (standbyState == STANDBY_DISABLED)
6120 : {
6121 : /* Mark the transaction aborted in pg_xact, no need for async stuff */
2947 andres 6122 20 : TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
6123 : }
6124 : else
6125 : {
4859 simon 6126 ECB : /*
6127 : * If a transaction completion record arrives that has as-yet
6128 : * unobserved subtransactions then this will not have been fully
6129 : * handled by the call to RecordKnownAssignedTransactionIds() in the
6130 : * main recovery loop in xlog.c. So we need to do bookkeeping again to
4790 bruce 6131 : * cover that case. This is confusing and it is easy to think this
6132 : * call is irrelevant, which has happened three times in development
6133 : * already. Leave it in.
4859 simon 6134 : */
4859 simon 6135 GIC 1409 : RecordKnownAssignedTransactionIds(max_xid);
4859 simon 6136 ECB :
2214 rhaas 6137 : /* Mark the transaction aborted in pg_xact, no need for async stuff */
2947 andres 6138 GIC 1409 : TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
4859 simon 6139 ECB :
6140 : /*
6141 : * We must update the ProcArray after we have marked clog.
6142 : */
1165 alvherre 6143 GIC 1409 : ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
6144 :
6145 : /*
6146 : * There are no invalidation messages to send or undo.
6147 : */
6148 :
6149 : /*
6150 : * Release locks, if any. There are no invalidations to send.
6151 : */
2209 simon 6152 1409 : if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
6153 863 : StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
6154 : }
6505 tgl 6155 ECB :
762 akapila 6156 GIC 1429 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6157 : {
762 akapila 6158 ECB : /* recover apply progress */
762 akapila 6159 GIC 5 : replorigin_advance(origin_id, parsed->origin_lsn, lsn,
6160 : false /* backward */ , false /* WAL */ );
6161 : }
6162 :
6505 tgl 6163 ECB : /* Make sure files supposed to be dropped are dropped */
619 fujii 6164 GIC 1429 : if (parsed->nrels > 0)
6165 : {
6166 : /*
6167 : * See comments about update of minimum recovery point on truncation,
6168 : * in xact_redo_commit().
6169 : */
6170 221 : XLogFlush(lsn);
6171 :
277 rhaas 6172 GNC 221 : DropRelationFiles(parsed->xlocators, parsed->nrels, true);
619 fujii 6173 ECB : }
6174 :
368 andres 6175 GIC 1429 : if (parsed->nstats > 0)
368 andres 6176 ECB : {
6177 : /* see equivalent call for relations above */
368 andres 6178 GIC 295 : XLogFlush(lsn);
368 andres 6179 ECB :
368 andres 6180 GIC 295 : pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
6181 : }
6505 tgl 6182 1429 : }
6183 :
8206 vadim4o 6184 ECB : void
3062 heikki.linnakangas 6185 GIC 20638 : xact_redo(XLogReaderState *record)
6186 : {
2947 andres 6187 20638 : uint8 info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
6188 :
6189 : /* Backup blocks are not used in xact records */
3062 heikki.linnakangas 6190 CBC 20638 : Assert(!XLogRecHasAnyBlockRefs(record));
6191 :
2125 alvherre 6192 20638 : if (info == XLOG_XACT_COMMIT)
6193 : {
6997 tgl 6194 GIC 18884 : xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
2947 andres 6195 ECB : xl_xact_parsed_commit parsed;
6196 :
2125 alvherre 6197 GIC 18884 : ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
2125 alvherre 6198 CBC 18884 : xact_redo_commit(&parsed, XLogRecGetXid(record),
2125 alvherre 6199 GIC 18884 : record->EndRecPtr, XLogRecGetOrigin(record));
2125 alvherre 6200 ECB : }
2125 alvherre 6201 GIC 1754 : else if (info == XLOG_XACT_COMMIT_PREPARED)
2125 alvherre 6202 ECB : {
2125 alvherre 6203 GIC 39 : xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
6204 : xl_xact_parsed_commit parsed;
6997 tgl 6205 ECB :
2125 alvherre 6206 GIC 39 : ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
2125 alvherre 6207 CBC 39 : xact_redo_commit(&parsed, parsed.twophase_xid,
2125 alvherre 6208 GIC 39 : record->EndRecPtr, XLogRecGetOrigin(record));
6209 :
2125 alvherre 6210 ECB : /* Delete TwoPhaseState gxact entry and/or 2PC file. */
2125 alvherre 6211 GIC 39 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
2125 alvherre 6212 CBC 39 : PrepareRedoRemove(parsed.twophase_xid, false);
2125 alvherre 6213 GIC 39 : LWLockRelease(TwoPhaseStateLock);
6505 tgl 6214 ECB : }
2125 alvherre 6215 GIC 1715 : else if (info == XLOG_XACT_ABORT)
6216 : {
6505 tgl 6217 CBC 1410 : xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2947 andres 6218 ECB : xl_xact_parsed_abort parsed;
6219 :
2125 alvherre 6220 GIC 1410 : ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
762 akapila 6221 CBC 1410 : xact_redo_abort(&parsed, XLogRecGetXid(record),
762 akapila 6222 GIC 1410 : record->EndRecPtr, XLogRecGetOrigin(record));
2125 alvherre 6223 ECB : }
2125 alvherre 6224 GIC 305 : else if (info == XLOG_XACT_ABORT_PREPARED)
6225 : {
2125 alvherre 6226 CBC 19 : xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2125 alvherre 6227 ECB : xl_xact_parsed_abort parsed;
6796 tgl 6228 :
2125 alvherre 6229 GIC 19 : ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
762 akapila 6230 19 : xact_redo_abort(&parsed, parsed.twophase_xid,
762 akapila 6231 CBC 19 : record->EndRecPtr, XLogRecGetOrigin(record));
2196 simon 6232 ECB :
2125 alvherre 6233 : /* Delete TwoPhaseState gxact entry and/or 2PC file. */
2125 alvherre 6234 GIC 19 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
2125 alvherre 6235 CBC 19 : PrepareRedoRemove(parsed.twophase_xid, false);
2125 alvherre 6236 GIC 19 : LWLockRelease(TwoPhaseStateLock);
6505 tgl 6237 ECB : }
6505 tgl 6238 GIC 286 : else if (info == XLOG_XACT_PREPARE)
6239 : {
2196 simon 6240 ECB : /*
2153 bruce 6241 : * Store xid and start/end pointers of the WAL record in TwoPhaseState
6242 : * gxact entry.
6243 : */
2125 alvherre 6244 CBC 69 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
2196 simon 6245 GIC 69 : PrepareRedoAdd(XLogRecGetData(record),
2196 simon 6246 ECB : record->ReadRecPtr,
6247 : record->EndRecPtr,
1838 simon 6248 GIC 69 : XLogRecGetOrigin(record));
2125 alvherre 6249 CBC 69 : LWLockRelease(TwoPhaseStateLock);
6505 tgl 6250 ECB : }
4859 simon 6251 CBC 217 : else if (info == XLOG_XACT_ASSIGNMENT)
6252 : {
4859 simon 6253 GIC 21 : xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record);
4859 simon 6254 ECB :
4714 simon 6255 CBC 21 : if (standbyState >= STANDBY_INITIALIZED)
4859 6256 21 : ProcArrayApplyXidAssignment(xlrec->xtop,
4859 simon 6257 GIC 21 : xlrec->nsubxacts, xlrec->xsub);
4859 simon 6258 ECB : }
990 akapila 6259 GIC 196 : else if (info == XLOG_XACT_INVALIDATIONS)
6260 : {
6261 : /*
6262 : * XXX we do ignore this for now, what matters are invalidations
6263 : * written into the commit record.
990 akapila 6264 ECB : */
6265 : }
6266 : else
6505 tgl 6267 UIC 0 : elog(PANIC, "xact_redo: unknown op code %u", info);
6505 tgl 6268 CBC 20638 : }
|