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