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