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