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