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