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