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 1261176 : IsTransactionState(void)
390 : {
391 1261176 : 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 1261176 : 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 961807 : IsAbortedTransactionBlockState(void)
410 : {
411 961807 : TransactionState s = CurrentTransactionState;
412 :
413 961807 : if (s->blockState == TBLOCK_ABORT ||
414 959825 : s->blockState == TBLOCK_SUBABORT)
415 2396 : return true;
416 :
417 959411 : 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 39375 : GetTopTransactionId(void)
429 : {
430 39375 : if (!FullTransactionIdIsValid(XactTopFullTransactionId))
431 700 : AssignTransactionId(&TopTransactionStateData);
432 39375 : 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 64671920 : GetTopTransactionIdIfAny(void)
444 : {
445 64671920 : 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 16800439 : GetCurrentTransactionId(void)
457 : {
458 16800439 : TransactionState s = CurrentTransactionState;
459 :
460 16800439 : if (!FullTransactionIdIsValid(s->fullTransactionId))
461 167966 : AssignTransactionId(s);
462 16800431 : 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 24781753 : GetCurrentTransactionIdIfAny(void)
474 : {
475 24781753 : 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 380 : GetCurrentFullTransactionId(void)
515 : {
516 380 : TransactionState s = CurrentTransactionState;
517 :
518 380 : if (!FullTransactionIdIsValid(s->fullTransactionId))
519 14 : AssignTransactionId(s);
520 380 : 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 24729416 : MarkCurrentTransactionIdLoggedIfAny(void)
544 : {
545 24729416 : if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId))
546 24388545 : CurrentTransactionState->didLogXid = true;
547 24729416 : }
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 24738312 : IsSubxactTopXidLogPending(void)
562 : {
563 : /* check whether it is already logged */
564 24738312 : if (CurrentTransactionState->topXidLogged)
565 102136 : return false;
566 :
567 : /* effective_wal_level has to be logical */
568 24636176 : if (!XLogLogicalInfoActive())
569 24022399 : return false;
570 :
571 : /* we need to be in a transaction state */
572 613777 : if (!IsTransactionState())
573 4307 : return false;
574 :
575 : /* it has to be a subtransaction */
576 609470 : if (!IsSubTransaction())
577 609237 : 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 163 : GetStableLatestTransactionId(void)
610 : {
611 : static LocalTransactionId lxid = InvalidLocalTransactionId;
612 : static TransactionId stablexid = InvalidTransactionId;
613 :
614 163 : if (lxid != MyProc->vxid.lxid)
615 : {
616 15 : lxid = MyProc->vxid.lxid;
617 15 : stablexid = GetTopTransactionIdIfAny();
618 15 : if (!TransactionIdIsValid(stablexid))
619 15 : stablexid = ReadNextTransactionId();
620 : }
621 :
622 : Assert(TransactionIdIsValid(stablexid));
623 :
624 163 : 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 172003 : AssignTransactionId(TransactionState s)
638 : {
639 172003 : bool isSubXact = (s->parent != NULL);
640 : ResourceOwner currentOwner;
641 172003 : 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 172003 : 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 172003 : if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId))
663 : {
664 626 : TransactionState p = s->parent;
665 : TransactionState *parents;
666 626 : size_t parentOffset = 0;
667 :
668 626 : parents = palloc_array(TransactionState, s->nestingLevel);
669 1845 : while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
670 : {
671 1219 : parents[parentOffset++] = p;
672 1219 : 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 1845 : while (parentOffset != 0)
680 1219 : AssignTransactionId(parents[--parentOffset]);
681 :
682 626 : 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 172003 : 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 172003 : s->fullTransactionId = GetNewTransactionId(isSubXact);
709 171995 : if (!isSubXact)
710 167402 : XactTopFullTransactionId = s->fullTransactionId;
711 :
712 171995 : if (isSubXact)
713 4593 : SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),
714 4593 : 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 171995 : if (!isSubXact)
721 167402 : 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 171995 : currentOwner = CurrentResourceOwner;
729 171995 : CurrentResourceOwner = s->curTransactionOwner;
730 :
731 171995 : XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));
732 :
733 171995 : 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 171995 : if (isSubXact && XLogStandbyInfoActive())
754 : {
755 4306 : unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);
756 4306 : nUnreportedXids++;
757 :
758 : /*
759 : * ensure this test matches similar one in
760 : * RecoverPreparedTransactions()
761 : */
762 4306 : 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 69 : xlrec.xtop = GetTopTransactionId();
772 : Assert(TransactionIdIsValid(xlrec.xtop));
773 69 : xlrec.nsubxacts = nUnreportedXids;
774 :
775 69 : XLogBeginInsert();
776 69 : XLogRegisterData(&xlrec, MinSizeOfXactAssignment);
777 69 : XLogRegisterData(unreportedXids,
778 : nUnreportedXids * sizeof(TransactionId));
779 :
780 69 : (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
781 :
782 69 : nUnreportedXids = 0;
783 : /* mark top, not current xact as having been logged */
784 69 : TopTransactionStateData.didLogXid = true;
785 : }
786 : }
787 171995 : }
788 :
789 : /*
790 : * GetCurrentSubTransactionId
791 : */
792 : SubTransactionId
793 9343243 : GetCurrentSubTransactionId(void)
794 : {
795 9343243 : TransactionState s = CurrentTransactionState;
796 :
797 9343243 : 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 7903474 : GetCurrentCommandId(bool used)
832 : {
833 : /* this is global to a transaction, not subtransaction-local */
834 7903474 : 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 4439259 : if (IsParallelWorker())
843 0 : ereport(ERROR,
844 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
845 : errmsg("cannot modify data in a parallel worker")));
846 :
847 4439259 : currentCommandIdUsed = true;
848 : }
849 7903474 : 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 2011 : SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
862 : {
863 : Assert(IsParallelWorker());
864 2011 : xactStartTimestamp = xact_ts;
865 2011 : stmtStartTimestamp = stmt_ts;
866 2011 : }
867 :
868 : /*
869 : * GetCurrentTransactionStartTimestamp
870 : */
871 : TimestampTz
872 45183 : GetCurrentTransactionStartTimestamp(void)
873 : {
874 45183 : return xactStartTimestamp;
875 : }
876 :
877 : /*
878 : * GetCurrentStatementStartTimestamp
879 : */
880 : TimestampTz
881 1533303 : GetCurrentStatementStartTimestamp(void)
882 : {
883 1533303 : 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 1273390 : GetCurrentTransactionStopTimestamp(void)
894 : {
895 1273390 : 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 1273390 : if (xactStopTimestamp == 0)
904 379629 : xactStopTimestamp = GetCurrentTimestamp();
905 :
906 1273390 : 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 773389 : SetCurrentStatementStartTimestamp(void)
917 : {
918 773389 : if (!IsParallelWorker())
919 771378 : stmtStartTimestamp = GetCurrentTimestamp();
920 : else
921 : Assert(stmtStartTimestamp != 0);
922 773389 : }
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 25671927 : GetCurrentTransactionNestLevel(void)
932 : {
933 25671927 : TransactionState s = CurrentTransactionState;
934 :
935 25671927 : return s->nestingLevel;
936 : }
937 :
938 :
939 : /*
940 : * TransactionIdIsCurrentTransactionId
941 : */
942 : bool
943 64628876 : 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 64628876 : if (!TransactionIdIsNormal(xid))
961 737831 : return false;
962 :
963 63891045 : if (TransactionIdEquals(xid, GetTopTransactionIdIfAny()))
964 37702070 : 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 26188975 : if (nParallelCurrentXids > 0)
973 : {
974 : int low,
975 : high;
976 :
977 2508239 : low = 0;
978 2508239 : high = nParallelCurrentXids - 1;
979 9803552 : while (low <= high)
980 : {
981 : int middle;
982 : TransactionId probe;
983 :
984 9688908 : middle = low + (high - low) / 2;
985 9688908 : probe = ParallelCurrentXids[middle];
986 9688908 : if (probe == xid)
987 2393595 : return true;
988 7295313 : else if (probe < xid)
989 7180675 : low = middle + 1;
990 : else
991 114638 : high = middle - 1;
992 : }
993 114644 : 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 47322515 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
1004 : {
1005 : int low,
1006 : high;
1007 :
1008 23760669 : if (s->state == TRANS_ABORT)
1009 0 : continue;
1010 23760669 : if (!FullTransactionIdIsValid(s->fullTransactionId))
1011 10840398 : continue; /* it can't have any child XIDs either */
1012 12920271 : if (TransactionIdEquals(xid, XidFromFullTransactionId(s->fullTransactionId)))
1013 117327 : return true;
1014 : /* As the childXids array is ordered, we can use binary search */
1015 12802944 : low = 0;
1016 12802944 : high = s->nChildXids - 1;
1017 12803835 : while (low <= high)
1018 : {
1019 : int middle;
1020 : TransactionId probe;
1021 :
1022 2454 : middle = low + (high - low) / 2;
1023 2454 : probe = s->childXids[middle];
1024 2454 : if (TransactionIdEquals(probe, xid))
1025 1563 : return true;
1026 891 : else if (TransactionIdPrecedes(probe, xid))
1027 803 : low = middle + 1;
1028 : else
1029 88 : high = middle - 1;
1030 : }
1031 : }
1032 :
1033 23561846 : 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 9962363 : TransactionStartedDuringRecovery(void)
1045 : {
1046 9962363 : 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 4677 : EnterParallelMode(void)
1082 : {
1083 4677 : TransactionState s = CurrentTransactionState;
1084 :
1085 : Assert(s->parallelModeLevel >= 0);
1086 :
1087 4677 : ++s->parallelModeLevel;
1088 4677 : }
1089 :
1090 : /*
1091 : * ExitParallelMode
1092 : */
1093 : void
1094 2658 : ExitParallelMode(void)
1095 : {
1096 2658 : TransactionState s = CurrentTransactionState;
1097 :
1098 : Assert(s->parallelModeLevel > 0);
1099 : Assert(s->parallelModeLevel > 1 || s->parallelChildXact ||
1100 : !ParallelContextActive());
1101 :
1102 2658 : --s->parallelModeLevel;
1103 2658 : }
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 32073062 : IsInParallelMode(void)
1120 : {
1121 32073062 : TransactionState s = CurrentTransactionState;
1122 :
1123 32073062 : return s->parallelModeLevel != 0 || s->parallelChildXact;
1124 : }
1125 :
1126 : /*
1127 : * CommandCounterIncrement
1128 : */
1129 : void
1130 1341080 : 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 1341080 : 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 721975 : if (IsInParallelMode() || IsParallelWorker())
1146 0 : ereport(ERROR,
1147 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
1148 : errmsg("cannot start commands during a parallel operation")));
1149 :
1150 721975 : currentCommandId += 1;
1151 721975 : 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 721975 : currentCommandIdUsed = false;
1159 :
1160 : /* Propagate new command ID into static snapshots */
1161 721975 : 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 721975 : AtCCI_LocalCache();
1170 : }
1171 1341076 : }
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 568 : ForceSyncCommit(void)
1183 : {
1184 568 : forceSyncCommit = true;
1185 568 : }
1186 :
1187 :
1188 : /* ----------------------------------------------------------------
1189 : * StartTransaction stuff
1190 : * ----------------------------------------------------------------
1191 : */
1192 :
1193 : /*
1194 : * AtStart_Cache
1195 : */
1196 : static void
1197 650613 : AtStart_Cache(void)
1198 : {
1199 650613 : AcceptInvalidationMessages();
1200 650613 : }
1201 :
1202 : /*
1203 : * AtStart_Memory
1204 : */
1205 : static void
1206 650613 : AtStart_Memory(void)
1207 : {
1208 650613 : TransactionState s = CurrentTransactionState;
1209 :
1210 : /*
1211 : * Remember the memory context that was active prior to transaction start.
1212 : */
1213 650613 : 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 650613 : if (TransactionAbortContext == NULL)
1223 19958 : TransactionAbortContext =
1224 19958 : 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 650613 : if (TopTransactionContext == NULL)
1236 19958 : TopTransactionContext =
1237 19958 : 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 650613 : CurTransactionContext = TopTransactionContext;
1246 650613 : s->curTransactionContext = CurTransactionContext;
1247 :
1248 : /* Make the CurTransactionContext active. */
1249 650613 : MemoryContextSwitchTo(CurTransactionContext);
1250 650613 : }
1251 :
1252 : /*
1253 : * AtStart_ResourceOwner
1254 : */
1255 : static void
1256 650613 : AtStart_ResourceOwner(void)
1257 : {
1258 650613 : 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 650613 : s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
1269 :
1270 650613 : TopTransactionResourceOwner = s->curTransactionOwner;
1271 650613 : CurTransactionResourceOwner = s->curTransactionOwner;
1272 650613 : CurrentResourceOwner = s->curTransactionOwner;
1273 650613 : }
1274 :
1275 : /* ----------------------------------------------------------------
1276 : * StartSubTransaction stuff
1277 : * ----------------------------------------------------------------
1278 : */
1279 :
1280 : /*
1281 : * AtSubStart_Memory
1282 : */
1283 : static void
1284 11046 : AtSubStart_Memory(void)
1285 : {
1286 11046 : TransactionState s = CurrentTransactionState;
1287 :
1288 : Assert(CurTransactionContext != NULL);
1289 :
1290 : /*
1291 : * Remember the context that was active prior to subtransaction start.
1292 : */
1293 11046 : 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 11046 : CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
1301 : "CurTransactionContext",
1302 : ALLOCSET_DEFAULT_SIZES);
1303 11046 : s->curTransactionContext = CurTransactionContext;
1304 :
1305 : /* Make the CurTransactionContext active. */
1306 11046 : MemoryContextSwitchTo(CurTransactionContext);
1307 11046 : }
1308 :
1309 : /*
1310 : * AtSubStart_ResourceOwner
1311 : */
1312 : static void
1313 11046 : AtSubStart_ResourceOwner(void)
1314 : {
1315 11046 : 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 11046 : s->curTransactionOwner =
1324 11046 : ResourceOwnerCreate(s->parent->curTransactionOwner,
1325 : "SubTransaction");
1326 :
1327 11046 : CurTransactionResourceOwner = s->curTransactionOwner;
1328 11046 : CurrentResourceOwner = s->curTransactionOwner;
1329 11046 : }
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 612931 : RecordTransactionCommit(void)
1346 : {
1347 612931 : TransactionId xid = GetTopTransactionIdIfAny();
1348 612931 : bool markXidCommitted = TransactionIdIsValid(xid);
1349 612931 : TransactionId latestXid = InvalidTransactionId;
1350 : int nrels;
1351 : RelFileLocator *rels;
1352 : int nchildren;
1353 : TransactionId *children;
1354 612931 : int ndroppedstats = 0;
1355 612931 : xl_xact_stats_item *droppedstats = NULL;
1356 612931 : int nmsgs = 0;
1357 612931 : SharedInvalidationMessage *invalMessages = NULL;
1358 612931 : 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 612931 : if (XLogLogicalInfoActive())
1369 14428 : LogLogicalInvalidations();
1370 :
1371 : /* Get data needed for commit record */
1372 612931 : nrels = smgrGetPendingDeletes(true, &rels);
1373 612931 : nchildren = xactGetCommittedChildren(&children);
1374 612931 : ndroppedstats = pgstat_get_transactional_drops(true, &droppedstats);
1375 612931 : if (XLogStandbyInfoActive())
1376 327180 : nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
1377 : &RelcacheInitFileInval);
1378 612931 : 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 612931 : 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 454321 : 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 454321 : if (nmsgs != 0)
1422 : {
1423 11752 : LogStandbyInvalidations(nmsgs, invalMessages,
1424 : RelcacheInitFileInval);
1425 11752 : 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 454321 : if (!wrote_xlog)
1435 408948 : 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 159697 : replorigin = (replorigin_xact_state.origin != InvalidReplOriginId &&
1446 1087 : 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 158610 : START_CRIT_SECTION();
1471 158610 : 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 158610 : pg_write_barrier();
1480 :
1481 : /*
1482 : * Insert the commit XLOG record.
1483 : */
1484 158610 : XactLogCommitRecord(GetCurrentTransactionStopTimestamp(),
1485 : nchildren, children, nrels, rels,
1486 : ndroppedstats, droppedstats,
1487 : nmsgs, invalMessages,
1488 : RelcacheInitFileInval,
1489 : MyXactFlags,
1490 : InvalidTransactionId, NULL /* plain commit */ );
1491 :
1492 158610 : if (replorigin)
1493 : /* Move LSNs forward for this replication origin */
1494 1087 : 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 158610 : if (!replorigin || replorigin_xact_state.origin_timestamp == 0)
1508 157636 : replorigin_xact_state.origin_timestamp = GetCurrentTransactionStopTimestamp();
1509 :
1510 158610 : TransactionTreeSetCommitTsData(xid, nchildren, children,
1511 : replorigin_xact_state.origin_timestamp,
1512 158610 : 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 203983 : if ((wrote_xlog && markXidCommitted &&
1541 203983 : synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
1542 52578 : forceSyncCommit || nrels > 0)
1543 : {
1544 151426 : XLogFlush(XactLastRecEnd);
1545 :
1546 : /*
1547 : * Now we may update the CLOG, if we wrote a COMMIT record above
1548 : */
1549 151426 : if (markXidCommitted)
1550 151426 : 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 52557 : 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 52557 : if (markXidCommitted)
1573 7184 : 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 203983 : if (markXidCommitted)
1581 : {
1582 158610 : MyProc->delayChkptFlags &= ~DELAY_CHKPT_IN_COMMIT;
1583 158610 : END_CRIT_SECTION();
1584 : }
1585 :
1586 : /* Compute latestXid while we have the child XIDs handy */
1587 203983 : 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 203983 : if (wrote_xlog && markXidCommitted)
1599 153912 : SyncRepWaitForLSN(XactLastRecEnd, true);
1600 :
1601 : /* remember end of last commit record */
1602 203983 : XactLastCommitEnd = XactLastRecEnd;
1603 :
1604 : /* Reset XactLastRecEnd until the next transaction writes something */
1605 203983 : XactLastRecEnd = 0;
1606 612931 : cleanup:
1607 : /* Clean up local data */
1608 612931 : if (rels)
1609 12587 : pfree(rels);
1610 612931 : if (ndroppedstats)
1611 14907 : pfree(droppedstats);
1612 :
1613 612931 : return latestXid;
1614 : }
1615 :
1616 :
1617 : /*
1618 : * AtCCI_LocalCache
1619 : */
1620 : static void
1621 721975 : 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 721975 : AtCCI_RelationMap();
1629 :
1630 : /*
1631 : * Make catalog changes visible to me for the next command.
1632 : */
1633 721975 : CommandEndInvalidationMessages();
1634 721971 : }
1635 :
1636 : /*
1637 : * AtCommit_Memory
1638 : */
1639 : static void
1640 615247 : AtCommit_Memory(void)
1641 : {
1642 615247 : 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 615247 : 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 615247 : 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 615247 : CurTransactionContext = NULL;
1665 615247 : s->curTransactionContext = NULL;
1666 615247 : }
1667 :
1668 : /* ----------------------------------------------------------------
1669 : * CommitSubTransaction stuff
1670 : * ----------------------------------------------------------------
1671 : */
1672 :
1673 : /*
1674 : * AtSubCommit_Memory
1675 : */
1676 : static void
1677 5645 : AtSubCommit_Memory(void)
1678 : {
1679 5645 : TransactionState s = CurrentTransactionState;
1680 :
1681 : Assert(s->parent != NULL);
1682 :
1683 : /* Return to parent transaction level's memory context. */
1684 5645 : CurTransactionContext = s->parent->curTransactionContext;
1685 5645 : 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 5645 : if (MemoryContextIsEmpty(s->curTransactionContext))
1694 : {
1695 5628 : MemoryContextDelete(s->curTransactionContext);
1696 5628 : s->curTransactionContext = NULL;
1697 : }
1698 5645 : }
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 3740 : AtSubCommit_childXids(void)
1707 : {
1708 3740 : 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 3740 : new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
1718 :
1719 : /* Allocate or enlarge the parent array if necessary */
1720 3740 : 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 1705 : new_maxChildXids = Min(new_nChildXids * 2,
1732 : (int) (MaxAllocSize / sizeof(TransactionId)));
1733 :
1734 1705 : 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 1705 : if (s->parent->childXids == NULL)
1746 : new_childXids =
1747 1660 : MemoryContextAlloc(TopTransactionContext,
1748 : new_maxChildXids * sizeof(TransactionId));
1749 : else
1750 45 : new_childXids = repalloc(s->parent->childXids,
1751 : new_maxChildXids * sizeof(TransactionId));
1752 :
1753 1705 : s->parent->childXids = new_childXids;
1754 1705 : 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 3740 : s->parent->childXids[s->parent->nChildXids] = XidFromFullTransactionId(s->fullTransactionId);
1767 :
1768 3740 : 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 3740 : s->parent->nChildXids = new_nChildXids;
1774 :
1775 : /* Release child's array to avoid leakage */
1776 3740 : if (s->childXids != NULL)
1777 1018 : pfree(s->childXids);
1778 : /* We must reset these to avoid double-free if fail later in commit */
1779 3740 : s->childXids = NULL;
1780 3740 : s->nChildXids = 0;
1781 3740 : s->maxChildXids = 0;
1782 3740 : }
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 40759 : RecordTransactionAbort(bool isSubXact)
1797 : {
1798 40759 : TransactionId xid = GetCurrentTransactionIdIfAny();
1799 : TransactionId latestXid;
1800 : int nrels;
1801 : RelFileLocator *rels;
1802 40759 : int ndroppedstats = 0;
1803 40759 : 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 40759 : if (!TransactionIdIsValid(xid))
1816 : {
1817 : /* Reset XactLastRecEnd until the next transaction writes something */
1818 31427 : if (!isSubXact)
1819 26879 : XactLastRecEnd = 0;
1820 31427 : 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 9332 : 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 9355 : 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 9332 : nrels = smgrGetPendingDeletes(false, &rels);
1847 9332 : nchildren = xactGetCommittedChildren(&children);
1848 9332 : ndroppedstats = pgstat_get_transactional_drops(false, &droppedstats);
1849 :
1850 : /* XXX do we really need a critical section here? */
1851 9332 : START_CRIT_SECTION();
1852 :
1853 : /* Write the ABORT record */
1854 9332 : if (isSubXact)
1855 853 : xact_time = GetCurrentTimestamp();
1856 : else
1857 : {
1858 8479 : xact_time = GetCurrentTransactionStopTimestamp();
1859 : }
1860 :
1861 9332 : XactLogAbortRecord(xact_time,
1862 : nchildren, children,
1863 : nrels, rels,
1864 : ndroppedstats, droppedstats,
1865 : MyXactFlags, InvalidTransactionId,
1866 : NULL);
1867 :
1868 9332 : 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 9332 : if (!isSubXact)
1883 8479 : 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 9332 : TransactionIdAbortTree(xid, nchildren, children);
1894 :
1895 9332 : END_CRIT_SECTION();
1896 :
1897 : /* Compute latestXid while we have the child XIDs handy */
1898 9332 : 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 9332 : if (isSubXact)
1907 853 : XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
1908 :
1909 : /* Reset XactLastRecEnd until the next transaction writes something */
1910 9332 : if (!isSubXact)
1911 8479 : XactLastRecEnd = 0;
1912 :
1913 : /* And clean up local data */
1914 9332 : if (rels)
1915 1381 : pfree(rels);
1916 9332 : if (ndroppedstats)
1917 1959 : pfree(droppedstats);
1918 :
1919 9332 : return latestXid;
1920 : }
1921 :
1922 : /*
1923 : * AtAbort_Memory
1924 : */
1925 : static void
1926 55878 : 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 55878 : if (TransactionAbortContext != NULL)
1937 55878 : MemoryContextSwitchTo(TransactionAbortContext);
1938 : else
1939 0 : MemoryContextSwitchTo(TopMemoryContext);
1940 55878 : }
1941 :
1942 : /*
1943 : * AtSubAbort_Memory
1944 : */
1945 : static void
1946 5401 : AtSubAbort_Memory(void)
1947 : {
1948 : Assert(TransactionAbortContext != NULL);
1949 :
1950 5401 : MemoryContextSwitchTo(TransactionAbortContext);
1951 5401 : }
1952 :
1953 :
1954 : /*
1955 : * AtAbort_ResourceOwner
1956 : */
1957 : static void
1958 35366 : 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 35366 : CurrentResourceOwner = TopTransactionResourceOwner;
1965 35366 : }
1966 :
1967 : /*
1968 : * AtSubAbort_ResourceOwner
1969 : */
1970 : static void
1971 5401 : AtSubAbort_ResourceOwner(void)
1972 : {
1973 5401 : TransactionState s = CurrentTransactionState;
1974 :
1975 : /* Make sure we have a valid ResourceOwner */
1976 5401 : CurrentResourceOwner = s->curTransactionOwner;
1977 5401 : }
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 35366 : AtCleanup_Memory(void)
2017 : {
2018 35366 : 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 35366 : MemoryContextSwitchTo(s->priorContext);
2030 :
2031 : /*
2032 : * Clear the special abort context for next time.
2033 : */
2034 35366 : if (TransactionAbortContext != NULL)
2035 35366 : 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 35366 : if (TopTransactionContext != NULL)
2043 35366 : 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 35366 : CurTransactionContext = NULL;
2051 35366 : s->curTransactionContext = NULL;
2052 35366 : }
2053 :
2054 :
2055 : /* ----------------------------------------------------------------
2056 : * CleanupSubTransaction stuff
2057 : * ----------------------------------------------------------------
2058 : */
2059 :
2060 : /*
2061 : * AtSubCleanup_Memory
2062 : */
2063 : static void
2064 5401 : AtSubCleanup_Memory(void)
2065 : {
2066 5401 : 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 5401 : MemoryContextSwitchTo(s->priorContext);
2077 :
2078 : /* Update CurTransactionContext (might not be same as priorContext) */
2079 5401 : CurTransactionContext = s->parent->curTransactionContext;
2080 :
2081 : /*
2082 : * Clear the special abort context for next time.
2083 : */
2084 5401 : if (TransactionAbortContext != NULL)
2085 5401 : 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 5401 : if (s->curTransactionContext)
2093 5401 : MemoryContextDelete(s->curTransactionContext);
2094 5401 : s->curTransactionContext = NULL;
2095 5401 : }
2096 :
2097 : /* ----------------------------------------------------------------
2098 : * interface routines
2099 : * ----------------------------------------------------------------
2100 : */
2101 :
2102 : /*
2103 : * StartTransaction
2104 : */
2105 : static void
2106 650613 : StartTransaction(void)
2107 : {
2108 : TransactionState s;
2109 : VirtualTransactionId vxid;
2110 :
2111 : /*
2112 : * Let's just make sure the state stack is empty
2113 : */
2114 650613 : s = &TopTransactionStateData;
2115 650613 : 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 650613 : s->state = TRANS_START;
2129 650613 : s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
2130 :
2131 : /* Determine if statements are logged in this transaction */
2132 650613 : 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 650613 : s->nestingLevel = 1;
2142 650613 : s->gucNestLevel = 1;
2143 650613 : s->childXids = NULL;
2144 650613 : s->nChildXids = 0;
2145 650613 : 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 650613 : 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 650613 : if (RecoveryInProgress())
2165 : {
2166 2338 : s->startedInRecovery = true;
2167 2338 : XactReadOnly = true;
2168 : }
2169 : else
2170 : {
2171 648275 : s->startedInRecovery = false;
2172 648275 : XactReadOnly = DefaultXactReadOnly;
2173 : }
2174 650613 : XactDeferrable = DefaultXactDeferrable;
2175 650613 : XactIsoLevel = DefaultXactIsoLevel;
2176 650613 : forceSyncCommit = false;
2177 650613 : MyXactFlags = 0;
2178 :
2179 : /*
2180 : * reinitialize within-transaction counters
2181 : */
2182 650613 : s->subTransactionId = TopSubTransactionId;
2183 650613 : currentSubTransactionId = TopSubTransactionId;
2184 650613 : currentCommandId = FirstCommandId;
2185 650613 : currentCommandIdUsed = false;
2186 :
2187 : /*
2188 : * initialize reported xid accounting
2189 : */
2190 650613 : nUnreportedXids = 0;
2191 650613 : s->didLogXid = false;
2192 :
2193 : /*
2194 : * must initialize resource-management stuff first
2195 : */
2196 650613 : AtStart_Memory();
2197 650613 : 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 650613 : vxid.procNumber = MyProcNumber;
2204 650613 : vxid.localTransactionId = GetNextLocalTransactionId();
2205 :
2206 : /*
2207 : * Lock the virtual transaction id before we announce it in the proc array
2208 : */
2209 650613 : 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 650613 : 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 650613 : if (!IsParallelWorker())
2231 : {
2232 644580 : if (!SPI_inside_nonatomic_context())
2233 642364 : xactStartTimestamp = stmtStartTimestamp;
2234 : else
2235 2216 : xactStartTimestamp = GetCurrentTimestamp();
2236 : }
2237 : else
2238 : Assert(xactStartTimestamp != 0);
2239 650613 : pgstat_report_xact_timestamp(xactStartTimestamp);
2240 : /* Mark xactStopTimestamp as unset. */
2241 650613 : xactStopTimestamp = 0;
2242 :
2243 : /*
2244 : * initialize other subsystems for new transaction
2245 : */
2246 650613 : AtStart_GUC();
2247 650613 : AtStart_Cache();
2248 650613 : AfterTriggerBeginXact();
2249 :
2250 : /*
2251 : * done with start processing, set current transaction state to "in
2252 : * progress"
2253 : */
2254 650613 : s->state = TRANS_INPROGRESS;
2255 :
2256 : /* Schedule transaction timeout */
2257 650613 : if (TransactionTimeout > 0)
2258 1 : enable_timeout_after(TRANSACTION_TIMEOUT, TransactionTimeout);
2259 :
2260 650613 : ShowTransactionState("StartTransaction");
2261 650613 : }
2262 :
2263 :
2264 : /*
2265 : * CommitTransaction
2266 : *
2267 : * NB: if you change this routine, better look at PrepareTransaction too!
2268 : */
2269 : static void
2270 615201 : CommitTransaction(void)
2271 : {
2272 615201 : TransactionState s = CurrentTransactionState;
2273 : TransactionId latestXid;
2274 : bool is_parallel_worker;
2275 :
2276 615201 : is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
2277 :
2278 : /* Enforce parallel mode restrictions during parallel worker commit. */
2279 615201 : if (is_parallel_worker)
2280 2003 : EnterParallelMode();
2281 :
2282 615201 : ShowTransactionState("CommitTransaction");
2283 :
2284 : /*
2285 : * check the current transaction state
2286 : */
2287 615201 : 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 621002 : 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 620894 : if (!PreCommit_Portals(false))
2312 615093 : 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 615093 : 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 615093 : AtEOXact_Parallel(true);
2333 615093 : if (is_parallel_worker)
2334 : {
2335 2003 : 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 613090 : 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 615093 : 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 615093 : 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 615089 : smgrDoPendingSyncs(true, is_parallel_worker);
2361 :
2362 : /* close large objects before lower-level cleanup */
2363 615089 : 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 615089 : 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 615089 : if (!is_parallel_worker)
2381 613086 : PreCommit_CheckForSerializationFailure();
2382 :
2383 : /* Prevent cancel/die interrupt while cleaning up */
2384 614934 : HOLD_INTERRUPTS();
2385 :
2386 : /* Commit updates to the relation map --- do this as late as possible */
2387 614934 : AtEOXact_RelationMap(true, is_parallel_worker);
2388 :
2389 : /*
2390 : * set the current transaction state information appropriately during
2391 : * commit processing
2392 : */
2393 614934 : s->state = TRANS_COMMIT;
2394 614934 : s->parallelModeLevel = 0;
2395 614934 : s->parallelChildXact = false; /* should be false already */
2396 :
2397 : /* Disable transaction timeout */
2398 614934 : if (TransactionTimeout > 0)
2399 1 : disable_timeout(TRANSACTION_TIMEOUT, false);
2400 :
2401 614934 : 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 612931 : 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 2003 : latestXid = InvalidTransactionId;
2416 :
2417 : /*
2418 : * Make sure the leader will know about any WAL we wrote before it
2419 : * commits.
2420 : */
2421 2003 : 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 614934 : 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 614934 : CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
2450 : : XACT_EVENT_COMMIT);
2451 :
2452 614934 : CurrentResourceOwner = NULL;
2453 614934 : ResourceOwnerRelease(TopTransactionResourceOwner,
2454 : RESOURCE_RELEASE_BEFORE_LOCKS,
2455 : true, true);
2456 :
2457 614934 : AtEOXact_Aio(true);
2458 :
2459 : /* Check we've released all buffer pins */
2460 614934 : AtEOXact_Buffers(true);
2461 :
2462 : /* Clean up the relation cache */
2463 614934 : AtEOXact_RelationCache(true);
2464 :
2465 : /* Clean up the type cache */
2466 614934 : 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 614934 : AtEOXact_Inval(true);
2476 :
2477 614934 : AtEOXact_MultiXact();
2478 :
2479 614934 : ResourceOwnerRelease(TopTransactionResourceOwner,
2480 : RESOURCE_RELEASE_LOCKS,
2481 : true, true);
2482 614934 : 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 614934 : 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 614934 : AtCommit_Notify();
2503 :
2504 : /*
2505 : * Everything after this should be purely internal-to-this-backend
2506 : * cleanup.
2507 : */
2508 614934 : AtEOXact_GUC(true, 1);
2509 614934 : AtEOXact_SPI(true);
2510 614934 : AtEOXact_Enum();
2511 614934 : AtEOXact_on_commit_actions(true);
2512 614934 : AtEOXact_Namespace(true, is_parallel_worker);
2513 614934 : AtEOXact_SMgr();
2514 614934 : AtEOXact_Files(true);
2515 614934 : AtEOXact_ComboCid();
2516 614934 : AtEOXact_HashTables(true);
2517 614934 : AtEOXact_PgStat(true, is_parallel_worker);
2518 614934 : AtEOXact_Snapshot(true, false);
2519 614934 : AtEOXact_ApplyLauncher(true);
2520 614934 : AtEOXact_LogicalRepWorkers(true);
2521 614934 : AtEOXact_LogicalCtl();
2522 614934 : pgstat_report_xact_timestamp(0);
2523 :
2524 614934 : ResourceOwnerDelete(TopTransactionResourceOwner);
2525 614934 : s->curTransactionOwner = NULL;
2526 614934 : CurTransactionResourceOwner = NULL;
2527 614934 : TopTransactionResourceOwner = NULL;
2528 :
2529 614934 : AtCommit_Memory();
2530 :
2531 614934 : s->fullTransactionId = InvalidFullTransactionId;
2532 614934 : s->subTransactionId = InvalidSubTransactionId;
2533 614934 : s->nestingLevel = 0;
2534 614934 : s->gucNestLevel = 0;
2535 614934 : s->childXids = NULL;
2536 614934 : s->nChildXids = 0;
2537 614934 : s->maxChildXids = 0;
2538 :
2539 614934 : XactTopFullTransactionId = InvalidFullTransactionId;
2540 614934 : nParallelCurrentXids = 0;
2541 :
2542 : /*
2543 : * done with commit processing, set current transaction state back to
2544 : * default
2545 : */
2546 614934 : s->state = TRANS_DEFAULT;
2547 :
2548 614934 : RESUME_INTERRUPTS();
2549 614934 : }
2550 :
2551 :
2552 : /*
2553 : * PrepareTransaction
2554 : *
2555 : * NB: if you change this routine, better look at CommitTransaction too!
2556 : */
2557 : static void
2558 380 : PrepareTransaction(void)
2559 : {
2560 380 : TransactionState s = CurrentTransactionState;
2561 380 : FullTransactionId fxid = GetCurrentFullTransactionId();
2562 : GlobalTransaction gxact;
2563 : TimestampTz prepared_at;
2564 :
2565 : Assert(!IsInParallelMode());
2566 :
2567 380 : ShowTransactionState("PrepareTransaction");
2568 :
2569 : /*
2570 : * check the current transaction state
2571 : */
2572 380 : 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 382 : 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 382 : if (!PreCommit_Portals(true))
2596 380 : break;
2597 : }
2598 :
2599 380 : 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 379 : 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 379 : 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 379 : smgrDoPendingSyncs(true, false);
2623 :
2624 : /* close large objects before lower-level cleanup */
2625 379 : 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 379 : 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 379 : 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 334 : 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 334 : HOLD_INTERRUPTS();
2673 :
2674 : /*
2675 : * set the current transaction state information appropriately during
2676 : * prepare processing
2677 : */
2678 334 : s->state = TRANS_PREPARE;
2679 :
2680 : /* Disable transaction timeout */
2681 334 : if (TransactionTimeout > 0)
2682 0 : disable_timeout(TRANSACTION_TIMEOUT, false);
2683 :
2684 334 : 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 334 : gxact = MarkAsPreparing(fxid, prepareGID, prepared_at,
2691 : GetUserId(), MyDatabaseId);
2692 315 : 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 315 : StartPrepare(gxact);
2711 :
2712 315 : AtPrepare_Notify();
2713 315 : AtPrepare_Locks();
2714 313 : AtPrepare_PredicateLocks();
2715 313 : AtPrepare_PgStat();
2716 313 : AtPrepare_MultiXact();
2717 313 : 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 313 : 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 313 : 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 313 : 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 313 : 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 313 : CallXactCallbacks(XACT_EVENT_PREPARE);
2760 :
2761 313 : ResourceOwnerRelease(TopTransactionResourceOwner,
2762 : RESOURCE_RELEASE_BEFORE_LOCKS,
2763 : true, true);
2764 :
2765 313 : AtEOXact_Aio(true);
2766 :
2767 : /* Check we've released all buffer pins */
2768 313 : AtEOXact_Buffers(true);
2769 :
2770 : /* Clean up the relation cache */
2771 313 : AtEOXact_RelationCache(true);
2772 :
2773 : /* Clean up the type cache */
2774 313 : AtEOXact_TypeCache();
2775 :
2776 : /* notify doesn't need a postprepare call */
2777 :
2778 313 : PostPrepare_PgStat();
2779 :
2780 313 : PostPrepare_Inval();
2781 :
2782 313 : PostPrepare_smgr();
2783 :
2784 313 : PostPrepare_MultiXact(fxid);
2785 :
2786 313 : PostPrepare_PredicateLocks(fxid);
2787 :
2788 313 : ResourceOwnerRelease(TopTransactionResourceOwner,
2789 : RESOURCE_RELEASE_LOCKS,
2790 : true, true);
2791 313 : 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 313 : PostPrepare_Twophase();
2801 :
2802 : /* PREPARE acts the same as COMMIT as far as GUC is concerned */
2803 313 : AtEOXact_GUC(true, 1);
2804 313 : AtEOXact_SPI(true);
2805 313 : AtEOXact_Enum();
2806 313 : AtEOXact_on_commit_actions(true);
2807 313 : AtEOXact_Namespace(true, false);
2808 313 : AtEOXact_SMgr();
2809 313 : AtEOXact_Files(true);
2810 313 : AtEOXact_ComboCid();
2811 313 : AtEOXact_HashTables(true);
2812 : /* don't call AtEOXact_PgStat here; we fixed pgstat state above */
2813 313 : AtEOXact_Snapshot(true, true);
2814 : /* we treat PREPARE as ROLLBACK so far as waking workers goes */
2815 313 : AtEOXact_ApplyLauncher(false);
2816 313 : AtEOXact_LogicalRepWorkers(false);
2817 313 : AtEOXact_LogicalCtl();
2818 313 : pgstat_report_xact_timestamp(0);
2819 :
2820 313 : CurrentResourceOwner = NULL;
2821 313 : ResourceOwnerDelete(TopTransactionResourceOwner);
2822 313 : s->curTransactionOwner = NULL;
2823 313 : CurTransactionResourceOwner = NULL;
2824 313 : TopTransactionResourceOwner = NULL;
2825 :
2826 313 : AtCommit_Memory();
2827 :
2828 313 : s->fullTransactionId = InvalidFullTransactionId;
2829 313 : s->subTransactionId = InvalidSubTransactionId;
2830 313 : s->nestingLevel = 0;
2831 313 : s->gucNestLevel = 0;
2832 313 : s->childXids = NULL;
2833 313 : s->nChildXids = 0;
2834 313 : s->maxChildXids = 0;
2835 :
2836 313 : XactTopFullTransactionId = InvalidFullTransactionId;
2837 313 : nParallelCurrentXids = 0;
2838 :
2839 : /*
2840 : * done with 1st phase commit processing, set current transaction state
2841 : * back to default
2842 : */
2843 313 : s->state = TRANS_DEFAULT;
2844 :
2845 313 : RESUME_INTERRUPTS();
2846 313 : }
2847 :
2848 :
2849 : /*
2850 : * AbortTransaction
2851 : */
2852 : static void
2853 35366 : AbortTransaction(void)
2854 : {
2855 35366 : TransactionState s = CurrentTransactionState;
2856 : TransactionId latestXid;
2857 : bool is_parallel_worker;
2858 :
2859 : /* Prevent cancel/die interrupt while cleaning up */
2860 35366 : HOLD_INTERRUPTS();
2861 :
2862 : /* Disable transaction timeout */
2863 35366 : if (TransactionTimeout > 0)
2864 1 : disable_timeout(TRANSACTION_TIMEOUT, false);
2865 :
2866 : /* Make sure we have a valid memory context and resource owner */
2867 35366 : AtAbort_Memory();
2868 35366 : 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 35366 : LWLockReleaseAll();
2877 :
2878 : /*
2879 : * Cleanup waiting for LSN if any.
2880 : */
2881 35366 : WaitLSNCleanup();
2882 :
2883 : /* Clear wait information and command progress indicator */
2884 35366 : pgstat_report_wait_end();
2885 35366 : pgstat_progress_end_command();
2886 :
2887 35366 : pgaio_error_cleanup();
2888 :
2889 : /* Clean up buffer content locks, too */
2890 35366 : UnlockBuffers();
2891 :
2892 : /* Reset WAL record construction state */
2893 35366 : XLogResetInsertion();
2894 :
2895 : /* Cancel condition variable sleep */
2896 35366 : 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 35366 : 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 35366 : 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 35366 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
2919 :
2920 : /*
2921 : * check the current transaction state
2922 : */
2923 35366 : is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
2924 35366 : 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 35366 : 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 35366 : SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
2946 :
2947 : /* Forget about any active REINDEX. */
2948 35366 : ResetReindexState(s->nestingLevel);
2949 :
2950 : /* Reset logical streaming state. */
2951 35366 : ResetLogicalStreamingState();
2952 :
2953 : /* Reset snapshot export state. */
2954 35366 : 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 35366 : AtEOXact_Parallel(false);
2961 35366 : s->parallelModeLevel = 0;
2962 35366 : s->parallelChildXact = false; /* should be false already */
2963 :
2964 : /*
2965 : * do abort processing
2966 : */
2967 35366 : AfterTriggerEndXact(false); /* 'false' means it's abort */
2968 35366 : AtAbort_Portals();
2969 35366 : smgrDoPendingSyncs(false, is_parallel_worker);
2970 35366 : AtEOXact_LargeObject(false);
2971 35366 : AtAbort_Notify();
2972 35366 : AtEOXact_RelationMap(false, is_parallel_worker);
2973 35366 : 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 35366 : if (!is_parallel_worker)
2982 35358 : 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 35366 : 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 35366 : if (TopTransactionResourceOwner != NULL)
3010 : {
3011 35366 : if (is_parallel_worker)
3012 8 : CallXactCallbacks(XACT_EVENT_PARALLEL_ABORT);
3013 : else
3014 35358 : CallXactCallbacks(XACT_EVENT_ABORT);
3015 :
3016 35366 : ResourceOwnerRelease(TopTransactionResourceOwner,
3017 : RESOURCE_RELEASE_BEFORE_LOCKS,
3018 : false, true);
3019 35366 : AtEOXact_Aio(false);
3020 35366 : AtEOXact_Buffers(false);
3021 35366 : AtEOXact_RelationCache(false);
3022 35366 : AtEOXact_TypeCache();
3023 35366 : AtEOXact_Inval(false);
3024 35366 : AtEOXact_MultiXact();
3025 35366 : ResourceOwnerRelease(TopTransactionResourceOwner,
3026 : RESOURCE_RELEASE_LOCKS,
3027 : false, true);
3028 35366 : ResourceOwnerRelease(TopTransactionResourceOwner,
3029 : RESOURCE_RELEASE_AFTER_LOCKS,
3030 : false, true);
3031 35366 : smgrDoPendingDeletes(false);
3032 :
3033 35366 : AtEOXact_GUC(false, 1);
3034 35366 : AtEOXact_SPI(false);
3035 35366 : AtEOXact_Enum();
3036 35366 : AtEOXact_on_commit_actions(false);
3037 35366 : AtEOXact_Namespace(false, is_parallel_worker);
3038 35366 : AtEOXact_SMgr();
3039 35366 : AtEOXact_Files(false);
3040 35366 : AtEOXact_ComboCid();
3041 35366 : AtEOXact_HashTables(false);
3042 35366 : AtEOXact_PgStat(false, is_parallel_worker);
3043 35366 : AtEOXact_ApplyLauncher(false);
3044 35366 : AtEOXact_LogicalRepWorkers(false);
3045 35366 : AtEOXact_LogicalCtl();
3046 35366 : pgstat_report_xact_timestamp(0);
3047 : }
3048 :
3049 : /*
3050 : * State remains TRANS_ABORT until CleanupTransaction().
3051 : */
3052 35366 : RESUME_INTERRUPTS();
3053 35366 : }
3054 :
3055 : /*
3056 : * CleanupTransaction
3057 : */
3058 : static void
3059 35366 : CleanupTransaction(void)
3060 : {
3061 35366 : TransactionState s = CurrentTransactionState;
3062 :
3063 : /*
3064 : * State should still be TRANS_ABORT from AbortTransaction().
3065 : */
3066 35366 : 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 35366 : AtCleanup_Portals(); /* now safe to release portal memory */
3074 35366 : AtEOXact_Snapshot(false, true); /* and release the transaction's snapshots */
3075 :
3076 35366 : CurrentResourceOwner = NULL; /* and resource owner */
3077 35366 : if (TopTransactionResourceOwner)
3078 35366 : ResourceOwnerDelete(TopTransactionResourceOwner);
3079 35366 : s->curTransactionOwner = NULL;
3080 35366 : CurTransactionResourceOwner = NULL;
3081 35366 : TopTransactionResourceOwner = NULL;
3082 :
3083 35366 : AtCleanup_Memory(); /* and transaction memory */
3084 :
3085 35366 : s->fullTransactionId = InvalidFullTransactionId;
3086 35366 : s->subTransactionId = InvalidSubTransactionId;
3087 35366 : s->nestingLevel = 0;
3088 35366 : s->gucNestLevel = 0;
3089 35366 : s->childXids = NULL;
3090 35366 : s->nChildXids = 0;
3091 35366 : s->maxChildXids = 0;
3092 35366 : s->parallelModeLevel = 0;
3093 35366 : s->parallelChildXact = false;
3094 :
3095 35366 : XactTopFullTransactionId = InvalidFullTransactionId;
3096 35366 : nParallelCurrentXids = 0;
3097 :
3098 : /*
3099 : * done with abort processing, set current transaction state back to
3100 : * default
3101 : */
3102 35366 : s->state = TRANS_DEFAULT;
3103 35366 : }
3104 :
3105 : /*
3106 : * StartTransactionCommand
3107 : */
3108 : void
3109 754901 : StartTransactionCommand(void)
3110 : {
3111 754901 : TransactionState s = CurrentTransactionState;
3112 :
3113 754901 : switch (s->blockState)
3114 : {
3115 : /*
3116 : * if we aren't in a transaction block, we just do our usual start
3117 : * transaction.
3118 : */
3119 648562 : case TBLOCK_DEFAULT:
3120 648562 : StartTransaction();
3121 648562 : s->blockState = TBLOCK_STARTED;
3122 648562 : 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 105145 : case TBLOCK_INPROGRESS:
3132 : case TBLOCK_IMPLICIT_INPROGRESS:
3133 : case TBLOCK_SUBINPROGRESS:
3134 105145 : 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 1194 : case TBLOCK_ABORT:
3145 : case TBLOCK_SUBABORT:
3146 1194 : 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 754901 : MemoryContextSwitchTo(CurTransactionContext);
3174 754901 : }
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 722143 : SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)
3187 : {
3188 722143 : s->save_XactIsoLevel = XactIsoLevel;
3189 722143 : s->save_XactReadOnly = XactReadOnly;
3190 722143 : s->save_XactDeferrable = XactDeferrable;
3191 722143 : }
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 721848 : CommitTransactionCommand(void)
3208 : {
3209 : /*
3210 : * Repeatedly call CommitTransactionCommandInternal() until all the work
3211 : * is done.
3212 : */
3213 722139 : while (!CommitTransactionCommandInternal())
3214 : {
3215 : }
3216 721514 : }
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 722139 : CommitTransactionCommandInternal(void)
3226 : {
3227 722139 : TransactionState s = CurrentTransactionState;
3228 : SavedTransactionCharacteristics savetc;
3229 :
3230 : /* Must save in case we need to restore below */
3231 722139 : SaveTransactionCharacteristics(&savetc);
3232 :
3233 722139 : 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 603840 : case TBLOCK_STARTED:
3252 603840 : CommitTransaction();
3253 603829 : s->blockState = TBLOCK_DEFAULT;
3254 603829 : 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 12756 : case TBLOCK_BEGIN:
3263 12756 : s->blockState = TBLOCK_INPROGRESS;
3264 12756 : 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 81572 : case TBLOCK_INPROGRESS:
3272 : case TBLOCK_IMPLICIT_INPROGRESS:
3273 : case TBLOCK_SUBINPROGRESS:
3274 81572 : CommandCounterIncrement();
3275 81572 : break;
3276 :
3277 : /*
3278 : * We are completing a "COMMIT" command. Do it and return to the
3279 : * idle state.
3280 : */
3281 8949 : case TBLOCK_END:
3282 8949 : CommitTransaction();
3283 8710 : s->blockState = TBLOCK_DEFAULT;
3284 8710 : if (s->chain)
3285 : {
3286 8 : StartTransaction();
3287 8 : s->blockState = TBLOCK_INPROGRESS;
3288 8 : s->chain = false;
3289 8 : RestoreTransactionCharacteristics(&savetc);
3290 : }
3291 8710 : 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 919 : case TBLOCK_ABORT_END:
3308 919 : CleanupTransaction();
3309 919 : s->blockState = TBLOCK_DEFAULT;
3310 919 : if (s->chain)
3311 : {
3312 8 : StartTransaction();
3313 8 : s->blockState = TBLOCK_INPROGRESS;
3314 8 : s->chain = false;
3315 8 : RestoreTransactionCharacteristics(&savetc);
3316 : }
3317 919 : 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 1786 : case TBLOCK_ABORT_PENDING:
3325 1786 : AbortTransaction();
3326 1786 : CleanupTransaction();
3327 1786 : s->blockState = TBLOCK_DEFAULT;
3328 1786 : if (s->chain)
3329 : {
3330 12 : StartTransaction();
3331 12 : s->blockState = TBLOCK_INPROGRESS;
3332 12 : s->chain = false;
3333 12 : RestoreTransactionCharacteristics(&savetc);
3334 : }
3335 1786 : break;
3336 :
3337 : /*
3338 : * We are completing a "PREPARE TRANSACTION" command. Do it and
3339 : * return to the idle state.
3340 : */
3341 266 : case TBLOCK_PREPARE:
3342 266 : PrepareTransaction();
3343 201 : s->blockState = TBLOCK_DEFAULT;
3344 201 : 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 10564 : case TBLOCK_SUBBEGIN:
3352 10564 : StartSubTransaction();
3353 10564 : s->blockState = TBLOCK_SUBINPROGRESS;
3354 10564 : 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 266 : case TBLOCK_SUBRELEASE:
3363 : do
3364 : {
3365 266 : CommitSubTransaction();
3366 266 : s = CurrentTransactionState; /* changed by pop */
3367 266 : } while (s->blockState == TBLOCK_SUBRELEASE);
3368 :
3369 : Assert(s->blockState == TBLOCK_INPROGRESS ||
3370 : s->blockState == TBLOCK_SUBINPROGRESS);
3371 179 : 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 612 : case TBLOCK_SUBCOMMIT:
3383 : do
3384 : {
3385 612 : CommitSubTransaction();
3386 612 : s = CurrentTransactionState; /* changed by pop */
3387 612 : } while (s->blockState == TBLOCK_SUBCOMMIT);
3388 : /* If we had a COMMIT command, finish off the main xact too */
3389 523 : if (s->blockState == TBLOCK_END)
3390 : {
3391 : Assert(s->parent == NULL);
3392 409 : CommitTransaction();
3393 392 : s->blockState = TBLOCK_DEFAULT;
3394 392 : 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 114 : else if (s->blockState == TBLOCK_PREPARE)
3403 : {
3404 : Assert(s->parent == NULL);
3405 114 : PrepareTransaction();
3406 112 : s->blockState = TBLOCK_DEFAULT;
3407 : }
3408 : else
3409 0 : elog(ERROR, "CommitTransactionCommand: unexpected state %s",
3410 : BlockStateAsString(s->blockState));
3411 504 : 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 337 : case TBLOCK_SUBRESTART:
3438 : {
3439 : char *name;
3440 : int savepointLevel;
3441 :
3442 : /* save name and keep Cleanup from freeing it */
3443 337 : name = s->name;
3444 337 : s->name = NULL;
3445 337 : savepointLevel = s->savepointLevel;
3446 :
3447 337 : AbortSubTransaction();
3448 337 : CleanupSubTransaction();
3449 :
3450 337 : DefineSavepoint(NULL);
3451 337 : s = CurrentTransactionState; /* changed by push */
3452 337 : s->name = name;
3453 337 : s->savepointLevel = savepointLevel;
3454 :
3455 : /* This is the same as TBLOCK_SUBBEGIN case */
3456 : Assert(s->blockState == TBLOCK_SUBBEGIN);
3457 337 : StartSubTransaction();
3458 337 : s->blockState = TBLOCK_SUBINPROGRESS;
3459 : }
3460 337 : break;
3461 :
3462 : /*
3463 : * Same as above, but the subtransaction had already failed, so we
3464 : * don't need AbortSubTransaction.
3465 : */
3466 145 : case TBLOCK_SUBABORT_RESTART:
3467 : {
3468 : char *name;
3469 : int savepointLevel;
3470 :
3471 : /* save name and keep Cleanup from freeing it */
3472 145 : name = s->name;
3473 145 : s->name = NULL;
3474 145 : savepointLevel = s->savepointLevel;
3475 :
3476 145 : CleanupSubTransaction();
3477 :
3478 145 : DefineSavepoint(NULL);
3479 145 : s = CurrentTransactionState; /* changed by push */
3480 145 : s->name = name;
3481 145 : s->savepointLevel = savepointLevel;
3482 :
3483 : /* This is the same as TBLOCK_SUBBEGIN case */
3484 : Assert(s->blockState == TBLOCK_SUBBEGIN);
3485 145 : StartSubTransaction();
3486 145 : s->blockState = TBLOCK_SUBINPROGRESS;
3487 : }
3488 145 : break;
3489 : }
3490 :
3491 : /* Done, no more iterations required */
3492 721514 : 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 34141 : AbortCurrentTransaction(void)
3502 : {
3503 : /*
3504 : * Repeatedly call AbortCurrentTransactionInternal() until all the work is
3505 : * done.
3506 : */
3507 34141 : while (!AbortCurrentTransactionInternal())
3508 : {
3509 : }
3510 34141 : }
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 34141 : AbortCurrentTransactionInternal(void)
3520 : {
3521 34141 : TransactionState s = CurrentTransactionState;
3522 :
3523 34141 : 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 31589 : case TBLOCK_STARTED:
3552 : case TBLOCK_IMPLICIT_INPROGRESS:
3553 31589 : AbortTransaction();
3554 31589 : CleanupTransaction();
3555 31589 : s->blockState = TBLOCK_DEFAULT;
3556 31589 : 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 933 : case TBLOCK_INPROGRESS:
3577 : case TBLOCK_PARALLEL_INPROGRESS:
3578 933 : AbortTransaction();
3579 933 : s->blockState = TBLOCK_ABORT;
3580 : /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
3581 933 : 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 1185 : case TBLOCK_SUBINPROGRESS:
3640 1185 : AbortSubTransaction();
3641 1185 : s->blockState = TBLOCK_SUBABORT;
3642 1185 : 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 34141 : 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 118373 : PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
3699 : {
3700 : /*
3701 : * xact block already started?
3702 : */
3703 118373 : 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 118295 : 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 118295 : 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 118291 : if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
3732 117297 : 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 118291 : MyXactFlags |= XACT_FLAGS_NEEDIMMEDIATECOMMIT;
3737 118291 : }
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 1470 : WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
3762 : {
3763 1470 : CheckTransactionBlock(isTopLevel, false, stmtType);
3764 1470 : }
3765 :
3766 : void
3767 5117 : RequireTransactionBlock(bool isTopLevel, const char *stmtType)
3768 : {
3769 5117 : CheckTransactionBlock(isTopLevel, true, stmtType);
3770 5094 : }
3771 :
3772 : /*
3773 : * This is the implementation of the above two.
3774 : */
3775 : static void
3776 6587 : CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
3777 : {
3778 : /*
3779 : * xact block already started?
3780 : */
3781 6587 : if (IsTransactionBlock())
3782 6468 : 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 3058 : IsInTransactionBlock(bool isTopLevel)
3821 : {
3822 : /*
3823 : * Return true on same conditions that would make
3824 : * PreventInTransactionBlock error out
3825 : */
3826 3058 : if (IsTransactionBlock())
3827 98 : return true;
3828 :
3829 2960 : if (IsSubTransaction())
3830 0 : return true;
3831 :
3832 2960 : if (!isTopLevel)
3833 74 : return true;
3834 :
3835 2886 : if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
3836 2886 : CurrentTransactionState->blockState != TBLOCK_STARTED)
3837 0 : return true;
3838 :
3839 2886 : 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 2563 : RegisterXactCallback(XactCallback callback, void *arg)
3856 : {
3857 : XactCallbackItem *item;
3858 :
3859 : item = (XactCallbackItem *)
3860 2563 : MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
3861 2563 : item->callback = callback;
3862 2563 : item->arg = arg;
3863 2563 : item->next = Xact_callbacks;
3864 2563 : Xact_callbacks = item;
3865 2563 : }
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 1266086 : CallXactCallbacks(XactEvent event)
3890 : {
3891 : XactCallbackItem *item;
3892 : XactCallbackItem *next;
3893 :
3894 1548895 : for (item = Xact_callbacks; item; item = next)
3895 : {
3896 : /* allow callbacks to unregister themselves when called */
3897 282810 : next = item->next;
3898 282810 : item->callback(event, item->arg);
3899 : }
3900 1266085 : }
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 2563 : RegisterSubXactCallback(SubXactCallback callback, void *arg)
3916 : {
3917 : SubXactCallbackItem *item;
3918 :
3919 : item = (SubXactCallbackItem *)
3920 2563 : MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
3921 2563 : item->callback = callback;
3922 2563 : item->arg = arg;
3923 2563 : item->next = SubXact_callbacks;
3924 2563 : SubXact_callbacks = item;
3925 2563 : }
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 27737 : CallSubXactCallbacks(SubXactEvent event,
3950 : SubTransactionId mySubid,
3951 : SubTransactionId parentSubid)
3952 : {
3953 : SubXactCallbackItem *item;
3954 : SubXactCallbackItem *next;
3955 :
3956 49869 : for (item = SubXact_callbacks; item; item = next)
3957 : {
3958 : /* allow callbacks to unregister themselves when called */
3959 22132 : next = item->next;
3960 22132 : item->callback(event, mySubid, parentSubid, item->arg);
3961 : }
3962 27737 : }
3963 :
3964 :
3965 : /* ----------------------------------------------------------------
3966 : * transaction block support
3967 : * ----------------------------------------------------------------
3968 : */
3969 :
3970 : /*
3971 : * BeginTransactionBlock
3972 : * This executes a BEGIN command.
3973 : */
3974 : void
3975 12756 : BeginTransactionBlock(void)
3976 : {
3977 12756 : TransactionState s = CurrentTransactionState;
3978 :
3979 12756 : switch (s->blockState)
3980 : {
3981 : /*
3982 : * We are not inside a transaction block, so allow one to begin.
3983 : */
3984 12255 : case TBLOCK_STARTED:
3985 12255 : s->blockState = TBLOCK_BEGIN;
3986 12255 : 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 12756 : }
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 382 : PrepareTransactionBlock(const char *gid)
4044 : {
4045 : TransactionState s;
4046 : bool result;
4047 :
4048 : /* Set up to commit the current transaction */
4049 382 : result = EndTransactionBlock(false);
4050 :
4051 : /* If successful, change outer tblock state to PREPARE */
4052 382 : if (result)
4053 : {
4054 380 : s = CurrentTransactionState;
4055 :
4056 504 : while (s->parent != NULL)
4057 124 : s = s->parent;
4058 :
4059 380 : if (s->blockState == TBLOCK_END)
4060 : {
4061 : /* Save GID where PrepareTransaction can find it again */
4062 380 : prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
4063 :
4064 380 : 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 382 : 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 10281 : EndTransactionBlock(bool chain)
4096 : {
4097 10281 : TransactionState s = CurrentTransactionState;
4098 10281 : bool result = false;
4099 :
4100 10281 : switch (s->blockState)
4101 : {
4102 : /*
4103 : * We are in a transaction block, so tell CommitTransactionCommand
4104 : * to COMMIT.
4105 : */
4106 9199 : case TBLOCK_INPROGRESS:
4107 9199 : s->blockState = TBLOCK_END;
4108 9199 : result = true;
4109 9199 : 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 473 : case TBLOCK_ABORT:
4136 473 : s->blockState = TBLOCK_ABORT_END;
4137 473 : 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 523 : case TBLOCK_SUBINPROGRESS:
4144 1135 : while (s->parent != NULL)
4145 : {
4146 612 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4147 612 : s->blockState = TBLOCK_SUBCOMMIT;
4148 : else
4149 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4150 : BlockStateAsString(s->blockState));
4151 612 : s = s->parent;
4152 : }
4153 523 : if (s->blockState == TBLOCK_INPROGRESS)
4154 523 : s->blockState = TBLOCK_END;
4155 : else
4156 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4157 : BlockStateAsString(s->blockState));
4158 523 : result = true;
4159 523 : 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 10261 : s->chain = chain;
4244 :
4245 10261 : 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 2214 : UserAbortTransactionBlock(bool chain)
4256 : {
4257 2214 : TransactionState s = CurrentTransactionState;
4258 :
4259 2214 : 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 1642 : case TBLOCK_INPROGRESS:
4267 1642 : s->blockState = TBLOCK_ABORT_PENDING;
4268 1642 : 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 446 : case TBLOCK_ABORT:
4277 446 : s->blockState = TBLOCK_ABORT_END;
4278 446 : 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 2194 : s->chain = chain;
4365 2194 : }
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 48366 : BeginImplicitTransactionBlock(void)
4378 : {
4379 48366 : 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 48366 : if (s->blockState == TBLOCK_STARTED)
4391 5998 : s->blockState = TBLOCK_IMPLICIT_INPROGRESS;
4392 48366 : }
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 19189 : EndImplicitTransactionBlock(void)
4403 : {
4404 19189 : 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 19189 : if (s->blockState == TBLOCK_IMPLICIT_INPROGRESS)
4416 5385 : s->blockState = TBLOCK_STARTED;
4417 19189 : }
4418 :
4419 : /*
4420 : * DefineSavepoint
4421 : * This executes a SAVEPOINT command.
4422 : */
4423 : void
4424 1661 : DefineSavepoint(const char *name)
4425 : {
4426 1661 : 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 1661 : if (IsInParallelMode() || IsParallelWorker())
4436 0 : ereport(ERROR,
4437 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4438 : errmsg("cannot define savepoints during a parallel operation")));
4439 :
4440 1661 : switch (s->blockState)
4441 : {
4442 1653 : case TBLOCK_INPROGRESS:
4443 : case TBLOCK_SUBINPROGRESS:
4444 : /* Normal subtransaction start */
4445 1653 : PushTransaction();
4446 1653 : s = CurrentTransactionState; /* changed by push */
4447 :
4448 : /*
4449 : * Savepoint names, like the TransactionState block itself, live
4450 : * in TopTransactionContext.
4451 : */
4452 1653 : if (name)
4453 1171 : s->name = MemoryContextStrdup(TopTransactionContext, name);
4454 1653 : 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 1653 : }
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 183 : ReleaseSavepoint(const char *name)
4510 : {
4511 183 : 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 183 : if (IsInParallelMode() || IsParallelWorker())
4523 0 : ereport(ERROR,
4524 : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4525 : errmsg("cannot release savepoints during a parallel operation")));
4526 :
4527 183 : 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 179 : case TBLOCK_SUBINPROGRESS:
4552 179 : 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 266 : for (target = s; target; target = target->parent)
4578 : {
4579 266 : if (target->name && strcmp(target->name, name) == 0)
4580 179 : break;
4581 : }
4582 :
4583 179 : 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 179 : 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 179 : xact = CurrentTransactionState;
4600 : for (;;)
4601 : {
4602 87 : Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
4603 266 : xact->blockState = TBLOCK_SUBRELEASE;
4604 266 : if (xact == target)
4605 179 : break;
4606 87 : xact = xact->parent;
4607 : Assert(xact);
4608 : }
4609 179 : }
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 490 : RollbackToSavepoint(const char *name)
4619 : {
4620 490 : 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 490 : 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 490 : 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 482 : case TBLOCK_SUBINPROGRESS:
4662 : case TBLOCK_SUBABORT:
4663 482 : 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 520 : for (target = s; target; target = target->parent)
4687 : {
4688 520 : if (target->name && strcmp(target->name, name) == 0)
4689 482 : break;
4690 : }
4691 :
4692 482 : 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 482 : 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 482 : xact = CurrentTransactionState;
4709 : for (;;)
4710 : {
4711 520 : if (xact == target)
4712 482 : 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 482 : if (xact->blockState == TBLOCK_SUBINPROGRESS)
4726 337 : xact->blockState = TBLOCK_SUBRESTART;
4727 145 : else if (xact->blockState == TBLOCK_SUBABORT)
4728 145 : xact->blockState = TBLOCK_SUBABORT_RESTART;
4729 : else
4730 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4731 : BlockStateAsString(xact->blockState));
4732 482 : }
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 9393 : BeginInternalSubTransaction(const char *name)
4746 : {
4747 9393 : TransactionState s = CurrentTransactionState;
4748 9393 : 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 9393 : 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 9393 : switch (s->blockState)
4766 : {
4767 9393 : 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 9393 : PushTransaction();
4776 9393 : s = CurrentTransactionState; /* changed by push */
4777 :
4778 : /*
4779 : * Savepoint names, like the TransactionState block itself, live
4780 : * in TopTransactionContext.
4781 : */
4782 9393 : if (name)
4783 985 : s->name = MemoryContextStrdup(TopTransactionContext, name);
4784 9393 : 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 9393 : CommitTransactionCommand();
4806 9393 : StartTransactionCommand();
4807 :
4808 9393 : ExitOnAnyError = save_ExitOnAnyError;
4809 9393 : }
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 4767 : ReleaseCurrentSubTransaction(void)
4820 : {
4821 4767 : 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 4767 : if (s->blockState != TBLOCK_SUBINPROGRESS)
4830 0 : elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
4831 : BlockStateAsString(s->blockState));
4832 : Assert(s->state == TRANS_INPROGRESS);
4833 4767 : MemoryContextSwitchTo(CurTransactionContext);
4834 4767 : CommitSubTransaction();
4835 4767 : s = CurrentTransactionState; /* changed by pop */
4836 : Assert(s->state == TRANS_INPROGRESS);
4837 4767 : }
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 4626 : RollbackAndReleaseCurrentSubTransaction(void)
4848 : {
4849 4626 : 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 4626 : switch (s->blockState)
4858 : {
4859 : /* Must be in a subtransaction */
4860 4626 : case TBLOCK_SUBINPROGRESS:
4861 : case TBLOCK_SUBABORT:
4862 4626 : 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 4626 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4892 3641 : AbortSubTransaction();
4893 :
4894 : /* And clean it up, too */
4895 4626 : CleanupSubTransaction();
4896 :
4897 4626 : 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 4626 : }
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 20512 : AbortOutOfAnyTransaction(void)
4914 : {
4915 20512 : TransactionState s = CurrentTransactionState;
4916 :
4917 : /* Ensure we're not running in a doomed memory context */
4918 20512 : AtAbort_Memory();
4919 :
4920 : /*
4921 : * Get out of any transaction or nested transaction
4922 : */
4923 : do
4924 : {
4925 20514 : switch (s->blockState)
4926 : {
4927 19760 : case TBLOCK_DEFAULT:
4928 19760 : 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 19760 : break;
4947 738 : 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 738 : AbortTransaction();
4957 738 : CleanupTransaction();
4958 738 : s->blockState = TBLOCK_DEFAULT;
4959 738 : 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 2 : 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 2 : AbortSubTransaction();
4984 2 : CleanupSubTransaction();
4985 2 : s = CurrentTransactionState; /* changed by pop */
4986 2 : 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 20514 : } 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 20512 : MemoryContextSwitchTo(TopMemoryContext);
5016 20512 : }
5017 :
5018 : /*
5019 : * IsTransactionBlock --- are we within a transaction block?
5020 : */
5021 : bool
5022 354226 : IsTransactionBlock(void)
5023 : {
5024 354226 : TransactionState s = CurrentTransactionState;
5025 :
5026 354226 : if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
5027 285560 : return false;
5028 :
5029 68666 : 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 467316 : IsTransactionOrTransactionBlock(void)
5041 : {
5042 467316 : TransactionState s = CurrentTransactionState;
5043 :
5044 467316 : if (s->blockState == TBLOCK_DEFAULT)
5045 369678 : return false;
5046 :
5047 97638 : return true;
5048 : }
5049 :
5050 : /*
5051 : * TransactionBlockStatusCode - return status code to send in ReadyForQuery
5052 : */
5053 : char
5054 425109 : TransactionBlockStatusCode(void)
5055 : {
5056 425109 : TransactionState s = CurrentTransactionState;
5057 :
5058 425109 : switch (s->blockState)
5059 : {
5060 328140 : case TBLOCK_DEFAULT:
5061 : case TBLOCK_STARTED:
5062 328140 : return 'I'; /* idle --- not in transaction */
5063 95761 : 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 95761 : return 'T'; /* in transaction */
5074 1208 : 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 1208 : 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 743148 : IsSubTransaction(void)
5096 : {
5097 743148 : TransactionState s = CurrentTransactionState;
5098 :
5099 743148 : if (s->nestingLevel >= 2)
5100 250 : return true;
5101 :
5102 742898 : 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 11046 : StartSubTransaction(void)
5119 : {
5120 11046 : TransactionState s = CurrentTransactionState;
5121 :
5122 11046 : if (s->state != TRANS_DEFAULT)
5123 0 : elog(WARNING, "StartSubTransaction while in %s state",
5124 : TransStateAsString(s->state));
5125 :
5126 11046 : s->state = TRANS_START;
5127 :
5128 : /*
5129 : * Initialize subsystems for new subtransaction
5130 : *
5131 : * must initialize resource-management stuff first
5132 : */
5133 11046 : AtSubStart_Memory();
5134 11046 : AtSubStart_ResourceOwner();
5135 11046 : AfterTriggerBeginSubXact();
5136 :
5137 11046 : s->state = TRANS_INPROGRESS;
5138 :
5139 : /*
5140 : * Call start-of-subxact callbacks
5141 : */
5142 11046 : CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
5143 11046 : s->parent->subTransactionId);
5144 :
5145 11046 : ShowTransactionState("StartSubTransaction");
5146 11046 : }
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 5645 : CommitSubTransaction(void)
5156 : {
5157 5645 : TransactionState s = CurrentTransactionState;
5158 :
5159 5645 : ShowTransactionState("CommitSubTransaction");
5160 :
5161 5645 : 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 5645 : CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId,
5168 5645 : 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 5645 : AtEOSubXact_Parallel(true, s->subTransactionId);
5175 5645 : 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 5645 : s->state = TRANS_COMMIT;
5184 :
5185 : /* Must CCI to ensure commands of subtransaction are seen as done */
5186 5645 : 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 5645 : if (FullTransactionIdIsValid(s->fullTransactionId))
5196 3740 : AtSubCommit_childXids();
5197 5645 : AfterTriggerEndSubXact(true);
5198 5645 : AtSubCommit_Portals(s->subTransactionId,
5199 5645 : s->parent->subTransactionId,
5200 5645 : s->parent->nestingLevel,
5201 5645 : s->parent->curTransactionOwner);
5202 5645 : AtEOSubXact_LargeObject(true, s->subTransactionId,
5203 5645 : s->parent->subTransactionId);
5204 5645 : AtSubCommit_Notify();
5205 :
5206 5645 : CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
5207 5645 : s->parent->subTransactionId);
5208 :
5209 5645 : ResourceOwnerRelease(s->curTransactionOwner,
5210 : RESOURCE_RELEASE_BEFORE_LOCKS,
5211 : true, false);
5212 5645 : AtEOSubXact_RelationCache(true, s->subTransactionId,
5213 5645 : s->parent->subTransactionId);
5214 5645 : AtEOSubXact_TypeCache();
5215 5645 : AtEOSubXact_Inval(true);
5216 5645 : AtSubCommit_smgr();
5217 :
5218 : /*
5219 : * The only lock we actually release here is the subtransaction XID lock.
5220 : */
5221 5645 : CurrentResourceOwner = s->curTransactionOwner;
5222 5645 : if (FullTransactionIdIsValid(s->fullTransactionId))
5223 3740 : XactLockTableDelete(XidFromFullTransactionId(s->fullTransactionId));
5224 :
5225 : /*
5226 : * Other locks should get transferred to their parent resource owner.
5227 : */
5228 5645 : ResourceOwnerRelease(s->curTransactionOwner,
5229 : RESOURCE_RELEASE_LOCKS,
5230 : true, false);
5231 5645 : ResourceOwnerRelease(s->curTransactionOwner,
5232 : RESOURCE_RELEASE_AFTER_LOCKS,
5233 : true, false);
5234 :
5235 5645 : AtEOXact_GUC(true, s->gucNestLevel);
5236 5645 : AtEOSubXact_SPI(true, s->subTransactionId);
5237 5645 : AtEOSubXact_on_commit_actions(true, s->subTransactionId,
5238 5645 : s->parent->subTransactionId);
5239 5645 : AtEOSubXact_Namespace(true, s->subTransactionId,
5240 5645 : s->parent->subTransactionId);
5241 5645 : AtEOSubXact_Files(true, s->subTransactionId,
5242 5645 : s->parent->subTransactionId);
5243 5645 : AtEOSubXact_HashTables(true, s->nestingLevel);
5244 5645 : AtEOSubXact_PgStat(true, s->nestingLevel);
5245 5645 : 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 5645 : XactReadOnly = s->prevXactReadOnly;
5253 :
5254 5645 : CurrentResourceOwner = s->parent->curTransactionOwner;
5255 5645 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5256 5645 : ResourceOwnerDelete(s->curTransactionOwner);
5257 5645 : s->curTransactionOwner = NULL;
5258 :
5259 5645 : AtSubCommit_Memory();
5260 :
5261 5645 : s->state = TRANS_DEFAULT;
5262 :
5263 5645 : PopTransaction();
5264 5645 : }
5265 :
5266 : /*
5267 : * AbortSubTransaction
5268 : */
5269 : static void
5270 5401 : AbortSubTransaction(void)
5271 : {
5272 5401 : TransactionState s = CurrentTransactionState;
5273 :
5274 : /* Prevent cancel/die interrupt while cleaning up */
5275 5401 : HOLD_INTERRUPTS();
5276 :
5277 : /* Make sure we have a valid memory context and resource owner */
5278 5401 : AtSubAbort_Memory();
5279 5401 : 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 5401 : LWLockReleaseAll();
5291 :
5292 : /*
5293 : * Cleanup waiting for LSN if any.
5294 : */
5295 5401 : WaitLSNCleanup();
5296 :
5297 5401 : pgstat_report_wait_end();
5298 5401 : pgstat_progress_end_command();
5299 :
5300 5401 : pgaio_error_cleanup();
5301 :
5302 5401 : UnlockBuffers();
5303 :
5304 : /* Reset WAL record construction state */
5305 5401 : XLogResetInsertion();
5306 :
5307 : /* Cancel condition variable sleep */
5308 5401 : ConditionVariableCancelSleep();
5309 :
5310 : /*
5311 : * Also clean up any open wait for lock, since the lock manager will choke
5312 : * if we try to wait for another lock before doing this.
5313 : */
5314 5401 : LockErrorCleanup();
5315 :
5316 : /*
5317 : * If any timeout events are still active, make sure the timeout interrupt
5318 : * is scheduled. This covers possible loss of a timeout interrupt due to
5319 : * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
5320 : * We delay this till after LockErrorCleanup so that we don't uselessly
5321 : * reschedule lock or deadlock check timeouts.
5322 : */
5323 5401 : reschedule_timeouts();
5324 :
5325 : /*
5326 : * Re-enable signals, in case we got here by longjmp'ing out of a signal
5327 : * handler. We do this fairly early in the sequence so that the timeout
5328 : * infrastructure will be functional if needed while aborting.
5329 : */
5330 5401 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
5331 :
5332 : /*
5333 : * check the current transaction state
5334 : */
5335 5401 : ShowTransactionState("AbortSubTransaction");
5336 :
5337 5401 : if (s->state != TRANS_INPROGRESS)
5338 0 : elog(WARNING, "AbortSubTransaction while in %s state",
5339 : TransStateAsString(s->state));
5340 :
5341 5401 : s->state = TRANS_ABORT;
5342 :
5343 : /*
5344 : * Reset user ID which might have been changed transiently. (See notes in
5345 : * AbortTransaction.)
5346 : */
5347 5401 : SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
5348 :
5349 : /* Forget about any active REINDEX. */
5350 5401 : ResetReindexState(s->nestingLevel);
5351 :
5352 : /* Reset logical streaming state. */
5353 5401 : ResetLogicalStreamingState();
5354 :
5355 : /*
5356 : * No need for SnapBuildResetExportedSnapshotState() here, snapshot
5357 : * exports are not supported in subtransactions.
5358 : */
5359 :
5360 : /*
5361 : * If this subxact has started any unfinished parallel operation, clean up
5362 : * its workers and exit parallel mode. Don't warn about leaked resources.
5363 : */
5364 5401 : AtEOSubXact_Parallel(false, s->subTransactionId);
5365 5401 : s->parallelModeLevel = 0;
5366 :
5367 : /*
5368 : * We can skip all this stuff if the subxact failed before creating a
5369 : * ResourceOwner...
5370 : */
5371 5401 : if (s->curTransactionOwner)
5372 : {
5373 5401 : AfterTriggerEndSubXact(false);
5374 5401 : AtSubAbort_Portals(s->subTransactionId,
5375 5401 : s->parent->subTransactionId,
5376 : s->curTransactionOwner,
5377 5401 : s->parent->curTransactionOwner);
5378 5401 : AtEOSubXact_LargeObject(false, s->subTransactionId,
5379 5401 : s->parent->subTransactionId);
5380 5401 : AtSubAbort_Notify();
5381 :
5382 : /* Advertise the fact that we aborted in pg_xact. */
5383 5401 : (void) RecordTransactionAbort(true);
5384 :
5385 : /* Post-abort cleanup */
5386 5401 : if (FullTransactionIdIsValid(s->fullTransactionId))
5387 853 : AtSubAbort_childXids();
5388 :
5389 5401 : CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
5390 5401 : s->parent->subTransactionId);
5391 :
5392 5401 : ResourceOwnerRelease(s->curTransactionOwner,
5393 : RESOURCE_RELEASE_BEFORE_LOCKS,
5394 : false, false);
5395 :
5396 5401 : AtEOXact_Aio(false);
5397 5401 : AtEOSubXact_RelationCache(false, s->subTransactionId,
5398 5401 : s->parent->subTransactionId);
5399 5401 : AtEOSubXact_TypeCache();
5400 5401 : AtEOSubXact_Inval(false);
5401 5401 : ResourceOwnerRelease(s->curTransactionOwner,
5402 : RESOURCE_RELEASE_LOCKS,
5403 : false, false);
5404 5401 : ResourceOwnerRelease(s->curTransactionOwner,
5405 : RESOURCE_RELEASE_AFTER_LOCKS,
5406 : false, false);
5407 5401 : AtSubAbort_smgr();
5408 :
5409 5401 : AtEOXact_GUC(false, s->gucNestLevel);
5410 5401 : AtEOSubXact_SPI(false, s->subTransactionId);
5411 5401 : AtEOSubXact_on_commit_actions(false, s->subTransactionId,
5412 5401 : s->parent->subTransactionId);
5413 5401 : AtEOSubXact_Namespace(false, s->subTransactionId,
5414 5401 : s->parent->subTransactionId);
5415 5401 : AtEOSubXact_Files(false, s->subTransactionId,
5416 5401 : s->parent->subTransactionId);
5417 5401 : AtEOSubXact_HashTables(false, s->nestingLevel);
5418 5401 : AtEOSubXact_PgStat(false, s->nestingLevel);
5419 5401 : AtSubAbort_Snapshot(s->nestingLevel);
5420 : }
5421 :
5422 : /*
5423 : * Restore the upper transaction's read-only state, too. This should be
5424 : * redundant with GUC's cleanup but we may as well do it for consistency
5425 : * with the commit case.
5426 : */
5427 5401 : XactReadOnly = s->prevXactReadOnly;
5428 :
5429 5401 : RESUME_INTERRUPTS();
5430 5401 : }
5431 :
5432 : /*
5433 : * CleanupSubTransaction
5434 : *
5435 : * The caller has to make sure to always reassign CurrentTransactionState
5436 : * if it has a local pointer to it after calling this function.
5437 : */
5438 : static void
5439 5401 : CleanupSubTransaction(void)
5440 : {
5441 5401 : TransactionState s = CurrentTransactionState;
5442 :
5443 5401 : ShowTransactionState("CleanupSubTransaction");
5444 :
5445 5401 : if (s->state != TRANS_ABORT)
5446 0 : elog(WARNING, "CleanupSubTransaction while in %s state",
5447 : TransStateAsString(s->state));
5448 :
5449 5401 : AtSubCleanup_Portals(s->subTransactionId);
5450 :
5451 5401 : CurrentResourceOwner = s->parent->curTransactionOwner;
5452 5401 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5453 5401 : if (s->curTransactionOwner)
5454 5401 : ResourceOwnerDelete(s->curTransactionOwner);
5455 5401 : s->curTransactionOwner = NULL;
5456 :
5457 5401 : AtSubCleanup_Memory();
5458 :
5459 5401 : s->state = TRANS_DEFAULT;
5460 :
5461 5401 : PopTransaction();
5462 5401 : }
5463 :
5464 : /*
5465 : * PushTransaction
5466 : * Create transaction state stack entry for a subtransaction
5467 : *
5468 : * The caller has to make sure to always reassign CurrentTransactionState
5469 : * if it has a local pointer to it after calling this function.
5470 : */
5471 : static void
5472 11046 : PushTransaction(void)
5473 : {
5474 11046 : TransactionState p = CurrentTransactionState;
5475 : TransactionState s;
5476 :
5477 : /*
5478 : * We keep subtransaction state nodes in TopTransactionContext.
5479 : */
5480 : s = (TransactionState)
5481 11046 : MemoryContextAllocZero(TopTransactionContext,
5482 : sizeof(TransactionStateData));
5483 :
5484 : /*
5485 : * Assign a subtransaction ID, watching out for counter wraparound.
5486 : */
5487 11046 : currentSubTransactionId += 1;
5488 11046 : if (currentSubTransactionId == InvalidSubTransactionId)
5489 : {
5490 0 : currentSubTransactionId -= 1;
5491 0 : pfree(s);
5492 0 : ereport(ERROR,
5493 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5494 : errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
5495 : }
5496 :
5497 : /*
5498 : * We can now stack a minimally valid subtransaction without fear of
5499 : * failure.
5500 : */
5501 11046 : s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
5502 11046 : s->subTransactionId = currentSubTransactionId;
5503 11046 : s->parent = p;
5504 11046 : s->nestingLevel = p->nestingLevel + 1;
5505 11046 : s->gucNestLevel = NewGUCNestLevel();
5506 11046 : s->savepointLevel = p->savepointLevel;
5507 11046 : s->state = TRANS_DEFAULT;
5508 11046 : s->blockState = TBLOCK_SUBBEGIN;
5509 11046 : GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
5510 11046 : s->prevXactReadOnly = XactReadOnly;
5511 11046 : s->startedInRecovery = p->startedInRecovery;
5512 11046 : s->parallelModeLevel = 0;
5513 11046 : s->parallelChildXact = (p->parallelModeLevel != 0 || p->parallelChildXact);
5514 11046 : s->topXidLogged = false;
5515 :
5516 11046 : CurrentTransactionState = s;
5517 :
5518 : /*
5519 : * AbortSubTransaction and CleanupSubTransaction have to be able to cope
5520 : * with the subtransaction from here on out; in particular they should not
5521 : * assume that it necessarily has a transaction context, resource owner,
5522 : * or XID.
5523 : */
5524 11046 : }
5525 :
5526 : /*
5527 : * PopTransaction
5528 : * Pop back to parent transaction state
5529 : *
5530 : * The caller has to make sure to always reassign CurrentTransactionState
5531 : * if it has a local pointer to it after calling this function.
5532 : */
5533 : static void
5534 11046 : PopTransaction(void)
5535 : {
5536 11046 : TransactionState s = CurrentTransactionState;
5537 :
5538 11046 : if (s->state != TRANS_DEFAULT)
5539 0 : elog(WARNING, "PopTransaction while in %s state",
5540 : TransStateAsString(s->state));
5541 :
5542 11046 : if (s->parent == NULL)
5543 0 : elog(FATAL, "PopTransaction with no parent");
5544 :
5545 11046 : CurrentTransactionState = s->parent;
5546 :
5547 : /* Let's just make sure CurTransactionContext is good */
5548 11046 : CurTransactionContext = s->parent->curTransactionContext;
5549 11046 : MemoryContextSwitchTo(CurTransactionContext);
5550 :
5551 : /* Ditto for ResourceOwner links */
5552 11046 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5553 11046 : CurrentResourceOwner = s->parent->curTransactionOwner;
5554 :
5555 : /* Free the old child structure */
5556 11046 : if (s->name)
5557 2156 : pfree(s->name);
5558 11046 : pfree(s);
5559 11046 : }
5560 :
5561 : /*
5562 : * EstimateTransactionStateSpace
5563 : * Estimate the amount of space that will be needed by
5564 : * SerializeTransactionState. It would be OK to overestimate slightly,
5565 : * but it's simple for us to work out the precise value, so we do.
5566 : */
5567 : Size
5568 679 : EstimateTransactionStateSpace(void)
5569 : {
5570 : TransactionState s;
5571 679 : Size nxids = 0;
5572 679 : Size size = SerializedTransactionStateHeaderSize;
5573 :
5574 3050 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5575 : {
5576 2371 : if (FullTransactionIdIsValid(s->fullTransactionId))
5577 1359 : nxids = add_size(nxids, 1);
5578 2371 : nxids = add_size(nxids, s->nChildXids);
5579 : }
5580 :
5581 679 : return add_size(size, mul_size(sizeof(TransactionId), nxids));
5582 : }
5583 :
5584 : /*
5585 : * SerializeTransactionState
5586 : * Write out relevant details of our transaction state that will be
5587 : * needed by a parallel worker.
5588 : *
5589 : * We need to save and restore XactDeferrable, XactIsoLevel, and the XIDs
5590 : * associated with this transaction. These are serialized into a
5591 : * caller-supplied buffer big enough to hold the number of bytes reported by
5592 : * EstimateTransactionStateSpace(). We emit the XIDs in sorted order for the
5593 : * convenience of the receiving process.
5594 : */
5595 : void
5596 679 : SerializeTransactionState(Size maxsize, char *start_address)
5597 : {
5598 : TransactionState s;
5599 679 : Size nxids = 0;
5600 679 : Size i = 0;
5601 : TransactionId *workspace;
5602 : SerializedTransactionState *result;
5603 :
5604 679 : result = (SerializedTransactionState *) start_address;
5605 :
5606 679 : result->xactIsoLevel = XactIsoLevel;
5607 679 : result->xactDeferrable = XactDeferrable;
5608 679 : result->topFullTransactionId = XactTopFullTransactionId;
5609 679 : result->currentFullTransactionId =
5610 679 : CurrentTransactionState->fullTransactionId;
5611 679 : result->currentCommandId = currentCommandId;
5612 :
5613 : /*
5614 : * If we're running in a parallel worker and launching a parallel worker
5615 : * of our own, we can just pass along the information that was passed to
5616 : * us.
5617 : */
5618 679 : if (nParallelCurrentXids > 0)
5619 : {
5620 0 : result->nParallelCurrentXids = nParallelCurrentXids;
5621 0 : memcpy(&result->parallelCurrentXids[0], ParallelCurrentXids,
5622 : nParallelCurrentXids * sizeof(TransactionId));
5623 0 : return;
5624 : }
5625 :
5626 : /*
5627 : * OK, we need to generate a sorted list of XIDs that our workers should
5628 : * view as current. First, figure out how many there are.
5629 : */
5630 3050 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5631 : {
5632 2371 : if (FullTransactionIdIsValid(s->fullTransactionId))
5633 1359 : nxids = add_size(nxids, 1);
5634 2371 : nxids = add_size(nxids, s->nChildXids);
5635 : }
5636 : Assert(SerializedTransactionStateHeaderSize + nxids * sizeof(TransactionId)
5637 : <= maxsize);
5638 :
5639 : /* Copy them to our scratch space. */
5640 679 : workspace = palloc(nxids * sizeof(TransactionId));
5641 3050 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5642 : {
5643 2371 : if (FullTransactionIdIsValid(s->fullTransactionId))
5644 1359 : workspace[i++] = XidFromFullTransactionId(s->fullTransactionId);
5645 2371 : if (s->nChildXids > 0)
5646 0 : memcpy(&workspace[i], s->childXids,
5647 0 : s->nChildXids * sizeof(TransactionId));
5648 2371 : i += s->nChildXids;
5649 : }
5650 : Assert(i == nxids);
5651 :
5652 : /* Sort them. */
5653 679 : qsort(workspace, nxids, sizeof(TransactionId), xidComparator);
5654 :
5655 : /* Copy data into output area. */
5656 679 : result->nParallelCurrentXids = nxids;
5657 679 : memcpy(&result->parallelCurrentXids[0], workspace,
5658 : nxids * sizeof(TransactionId));
5659 : }
5660 :
5661 : /*
5662 : * StartParallelWorkerTransaction
5663 : * Start a parallel worker transaction, restoring the relevant
5664 : * transaction state serialized by SerializeTransactionState.
5665 : */
5666 : void
5667 2011 : StartParallelWorkerTransaction(char *tstatespace)
5668 : {
5669 : SerializedTransactionState *tstate;
5670 :
5671 : Assert(CurrentTransactionState->blockState == TBLOCK_DEFAULT);
5672 2011 : StartTransaction();
5673 :
5674 2011 : tstate = (SerializedTransactionState *) tstatespace;
5675 2011 : XactIsoLevel = tstate->xactIsoLevel;
5676 2011 : XactDeferrable = tstate->xactDeferrable;
5677 2011 : XactTopFullTransactionId = tstate->topFullTransactionId;
5678 2011 : CurrentTransactionState->fullTransactionId =
5679 : tstate->currentFullTransactionId;
5680 2011 : currentCommandId = tstate->currentCommandId;
5681 2011 : nParallelCurrentXids = tstate->nParallelCurrentXids;
5682 2011 : ParallelCurrentXids = &tstate->parallelCurrentXids[0];
5683 :
5684 2011 : CurrentTransactionState->blockState = TBLOCK_PARALLEL_INPROGRESS;
5685 2011 : }
5686 :
5687 : /*
5688 : * EndParallelWorkerTransaction
5689 : * End a parallel worker transaction.
5690 : */
5691 : void
5692 2003 : EndParallelWorkerTransaction(void)
5693 : {
5694 : Assert(CurrentTransactionState->blockState == TBLOCK_PARALLEL_INPROGRESS);
5695 2003 : CommitTransaction();
5696 2003 : CurrentTransactionState->blockState = TBLOCK_DEFAULT;
5697 2003 : }
5698 :
5699 : /*
5700 : * ShowTransactionState
5701 : * Debug support
5702 : */
5703 : static void
5704 1293687 : ShowTransactionState(const char *str)
5705 : {
5706 : /* skip work if message will definitely not be printed */
5707 1293687 : if (message_level_is_interesting(DEBUG5))
5708 0 : ShowTransactionStateRec(str, CurrentTransactionState);
5709 1293687 : }
5710 :
5711 : /*
5712 : * ShowTransactionStateRec
5713 : * Recursive subroutine for ShowTransactionState
5714 : */
5715 : static void
5716 0 : ShowTransactionStateRec(const char *str, TransactionState s)
5717 : {
5718 : StringInfoData buf;
5719 :
5720 0 : if (s->parent)
5721 : {
5722 : /*
5723 : * Since this function recurses, it could be driven to stack overflow.
5724 : * This is just a debugging aid, so we can leave out some details
5725 : * instead of erroring out with check_stack_depth().
5726 : */
5727 0 : if (stack_is_too_deep())
5728 0 : ereport(DEBUG5,
5729 : (errmsg_internal("%s(%d): parent omitted to avoid stack overflow",
5730 : str, s->nestingLevel)));
5731 : else
5732 0 : ShowTransactionStateRec(str, s->parent);
5733 : }
5734 :
5735 0 : initStringInfo(&buf);
5736 0 : if (s->nChildXids > 0)
5737 : {
5738 : int i;
5739 :
5740 0 : appendStringInfo(&buf, ", children: %u", s->childXids[0]);
5741 0 : for (i = 1; i < s->nChildXids; i++)
5742 0 : appendStringInfo(&buf, " %u", s->childXids[i]);
5743 : }
5744 0 : ereport(DEBUG5,
5745 : (errmsg_internal("%s(%d) name: %s; blockState: %s; state: %s, xid/subid/cid: %u/%u/%u%s%s",
5746 : str, s->nestingLevel,
5747 : s->name ? s->name : "unnamed",
5748 : BlockStateAsString(s->blockState),
5749 : TransStateAsString(s->state),
5750 : XidFromFullTransactionId(s->fullTransactionId),
5751 : s->subTransactionId,
5752 : currentCommandId,
5753 : currentCommandIdUsed ? " (used)" : "",
5754 : buf.data)));
5755 0 : pfree(buf.data);
5756 0 : }
5757 :
5758 : /*
5759 : * BlockStateAsString
5760 : * Debug support
5761 : */
5762 : static const char *
5763 0 : BlockStateAsString(TBlockState blockState)
5764 : {
5765 0 : switch (blockState)
5766 : {
5767 0 : case TBLOCK_DEFAULT:
5768 0 : return "DEFAULT";
5769 0 : case TBLOCK_STARTED:
5770 0 : return "STARTED";
5771 0 : case TBLOCK_BEGIN:
5772 0 : return "BEGIN";
5773 0 : case TBLOCK_INPROGRESS:
5774 0 : return "INPROGRESS";
5775 0 : case TBLOCK_IMPLICIT_INPROGRESS:
5776 0 : return "IMPLICIT_INPROGRESS";
5777 0 : case TBLOCK_PARALLEL_INPROGRESS:
5778 0 : return "PARALLEL_INPROGRESS";
5779 0 : case TBLOCK_END:
5780 0 : return "END";
5781 0 : case TBLOCK_ABORT:
5782 0 : return "ABORT";
5783 0 : case TBLOCK_ABORT_END:
5784 0 : return "ABORT_END";
5785 0 : case TBLOCK_ABORT_PENDING:
5786 0 : return "ABORT_PENDING";
5787 0 : case TBLOCK_PREPARE:
5788 0 : return "PREPARE";
5789 0 : case TBLOCK_SUBBEGIN:
5790 0 : return "SUBBEGIN";
5791 0 : case TBLOCK_SUBINPROGRESS:
5792 0 : return "SUBINPROGRESS";
5793 0 : case TBLOCK_SUBRELEASE:
5794 0 : return "SUBRELEASE";
5795 0 : case TBLOCK_SUBCOMMIT:
5796 0 : return "SUBCOMMIT";
5797 0 : case TBLOCK_SUBABORT:
5798 0 : return "SUBABORT";
5799 0 : case TBLOCK_SUBABORT_END:
5800 0 : return "SUBABORT_END";
5801 0 : case TBLOCK_SUBABORT_PENDING:
5802 0 : return "SUBABORT_PENDING";
5803 0 : case TBLOCK_SUBRESTART:
5804 0 : return "SUBRESTART";
5805 0 : case TBLOCK_SUBABORT_RESTART:
5806 0 : return "SUBABORT_RESTART";
5807 : }
5808 0 : return "UNRECOGNIZED";
5809 : }
5810 :
5811 : /*
5812 : * TransStateAsString
5813 : * Debug support
5814 : */
5815 : static const char *
5816 0 : TransStateAsString(TransState state)
5817 : {
5818 0 : switch (state)
5819 : {
5820 0 : case TRANS_DEFAULT:
5821 0 : return "DEFAULT";
5822 0 : case TRANS_START:
5823 0 : return "START";
5824 0 : case TRANS_INPROGRESS:
5825 0 : return "INPROGRESS";
5826 0 : case TRANS_COMMIT:
5827 0 : return "COMMIT";
5828 0 : case TRANS_ABORT:
5829 0 : return "ABORT";
5830 0 : case TRANS_PREPARE:
5831 0 : return "PREPARE";
5832 : }
5833 0 : return "UNRECOGNIZED";
5834 : }
5835 :
5836 : /*
5837 : * xactGetCommittedChildren
5838 : *
5839 : * Gets the list of committed children of the current transaction. The return
5840 : * value is the number of child transactions. *ptr is set to point to an
5841 : * array of TransactionIds. The array is allocated in TopTransactionContext;
5842 : * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
5843 : * If there are no subxacts, *ptr is set to NULL.
5844 : */
5845 : int
5846 622587 : xactGetCommittedChildren(TransactionId **ptr)
5847 : {
5848 622587 : TransactionState s = CurrentTransactionState;
5849 :
5850 622587 : if (s->nChildXids == 0)
5851 621945 : *ptr = NULL;
5852 : else
5853 642 : *ptr = s->childXids;
5854 :
5855 622587 : return s->nChildXids;
5856 : }
5857 :
5858 : /*
5859 : * XLOG support routines
5860 : */
5861 :
5862 :
5863 : /*
5864 : * Log the commit record for a plain or twophase transaction commit.
5865 : *
5866 : * A 2pc commit will be emitted when twophase_xid is valid, a plain one
5867 : * otherwise.
5868 : */
5869 : XLogRecPtr
5870 158883 : XactLogCommitRecord(TimestampTz commit_time,
5871 : int nsubxacts, TransactionId *subxacts,
5872 : int nrels, RelFileLocator *rels,
5873 : int ndroppedstats, xl_xact_stats_item *droppedstats,
5874 : int nmsgs, SharedInvalidationMessage *msgs,
5875 : bool relcacheInval,
5876 : int xactflags, TransactionId twophase_xid,
5877 : const char *twophase_gid)
5878 : {
5879 : xl_xact_commit xlrec;
5880 : xl_xact_xinfo xl_xinfo;
5881 : xl_xact_dbinfo xl_dbinfo;
5882 : xl_xact_subxacts xl_subxacts;
5883 : xl_xact_relfilelocators xl_relfilelocators;
5884 : xl_xact_stats_items xl_dropped_stats;
5885 : xl_xact_invals xl_invals;
5886 : xl_xact_twophase xl_twophase;
5887 : xl_xact_origin xl_origin;
5888 : uint8 info;
5889 :
5890 : Assert(CritSectionCount > 0);
5891 :
5892 158883 : xl_xinfo.xinfo = 0;
5893 :
5894 : /* decide between a plain and 2pc commit */
5895 158883 : if (!TransactionIdIsValid(twophase_xid))
5896 158610 : info = XLOG_XACT_COMMIT;
5897 : else
5898 273 : info = XLOG_XACT_COMMIT_PREPARED;
5899 :
5900 : /* First figure out and collect all the information needed */
5901 :
5902 158883 : xlrec.xact_time = commit_time;
5903 :
5904 158883 : if (relcacheInval)
5905 4650 : xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
5906 158883 : if (forceSyncCommit)
5907 568 : xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
5908 158883 : if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
5909 64750 : xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
5910 :
5911 : /*
5912 : * Check if the caller would like to ask standbys for immediate feedback
5913 : * once this commit is applied.
5914 : */
5915 158883 : if (synchronous_commit >= SYNCHRONOUS_COMMIT_REMOTE_APPLY)
5916 2 : xl_xinfo.xinfo |= XACT_COMPLETION_APPLY_FEEDBACK;
5917 :
5918 : /*
5919 : * Relcache invalidations requires information about the current database
5920 : * and so does logical decoding.
5921 : */
5922 158883 : if (nmsgs > 0 || XLogLogicalInfoActive())
5923 : {
5924 112568 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
5925 112568 : xl_dbinfo.dbId = MyDatabaseId;
5926 112568 : xl_dbinfo.tsId = MyDatabaseTableSpace;
5927 : }
5928 :
5929 158883 : if (nsubxacts > 0)
5930 : {
5931 539 : xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
5932 539 : xl_subxacts.nsubxacts = nsubxacts;
5933 : }
5934 :
5935 158883 : if (nrels > 0)
5936 : {
5937 12600 : xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
5938 12600 : xl_relfilelocators.nrels = nrels;
5939 12600 : info |= XLR_SPECIAL_REL_UPDATE;
5940 : }
5941 :
5942 158883 : if (ndroppedstats > 0)
5943 : {
5944 14920 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
5945 14920 : xl_dropped_stats.nitems = ndroppedstats;
5946 : }
5947 :
5948 158883 : if (nmsgs > 0)
5949 : {
5950 111629 : xl_xinfo.xinfo |= XACT_XINFO_HAS_INVALS;
5951 111629 : xl_invals.nmsgs = nmsgs;
5952 : }
5953 :
5954 158883 : if (TransactionIdIsValid(twophase_xid))
5955 : {
5956 273 : xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
5957 273 : xl_twophase.xid = twophase_xid;
5958 : Assert(twophase_gid != NULL);
5959 :
5960 273 : if (XLogLogicalInfoActive())
5961 41 : xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
5962 : }
5963 :
5964 : /* dump transaction origin information */
5965 158883 : if (replorigin_xact_state.origin != InvalidReplOriginId)
5966 : {
5967 1110 : xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
5968 :
5969 1110 : xl_origin.origin_lsn = replorigin_xact_state.origin_lsn;
5970 1110 : xl_origin.origin_timestamp = replorigin_xact_state.origin_timestamp;
5971 : }
5972 :
5973 158883 : if (xl_xinfo.xinfo != 0)
5974 115662 : info |= XLOG_XACT_HAS_INFO;
5975 :
5976 : /* Then include all the collected data into the commit record. */
5977 :
5978 158883 : XLogBeginInsert();
5979 :
5980 158883 : XLogRegisterData(&xlrec, sizeof(xl_xact_commit));
5981 :
5982 158883 : if (xl_xinfo.xinfo != 0)
5983 115662 : XLogRegisterData(&xl_xinfo.xinfo, sizeof(xl_xinfo.xinfo));
5984 :
5985 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
5986 112568 : XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo));
5987 :
5988 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
5989 : {
5990 539 : XLogRegisterData(&xl_subxacts,
5991 : MinSizeOfXactSubxacts);
5992 539 : XLogRegisterData(subxacts,
5993 : nsubxacts * sizeof(TransactionId));
5994 : }
5995 :
5996 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
5997 : {
5998 12600 : XLogRegisterData(&xl_relfilelocators,
5999 : MinSizeOfXactRelfileLocators);
6000 12600 : XLogRegisterData(rels,
6001 : nrels * sizeof(RelFileLocator));
6002 : }
6003 :
6004 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
6005 : {
6006 14920 : XLogRegisterData(&xl_dropped_stats,
6007 : MinSizeOfXactStatsItems);
6008 14920 : XLogRegisterData(droppedstats,
6009 : ndroppedstats * sizeof(xl_xact_stats_item));
6010 : }
6011 :
6012 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_INVALS)
6013 : {
6014 111629 : XLogRegisterData(&xl_invals, MinSizeOfXactInvals);
6015 111629 : XLogRegisterData(msgs,
6016 : nmsgs * sizeof(SharedInvalidationMessage));
6017 : }
6018 :
6019 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
6020 : {
6021 273 : XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase));
6022 273 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
6023 41 : XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1);
6024 : }
6025 :
6026 158883 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
6027 1110 : XLogRegisterData(&xl_origin, sizeof(xl_xact_origin));
6028 :
6029 : /* we allow filtering by xacts */
6030 158883 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
6031 :
6032 158883 : return XLogInsert(RM_XACT_ID, info);
6033 : }
6034 :
6035 : /*
6036 : * Log the commit record for a plain or twophase transaction abort.
6037 : *
6038 : * A 2pc abort will be emitted when twophase_xid is valid, a plain one
6039 : * otherwise.
6040 : */
6041 : XLogRecPtr
6042 9379 : XactLogAbortRecord(TimestampTz abort_time,
6043 : int nsubxacts, TransactionId *subxacts,
6044 : int nrels, RelFileLocator *rels,
6045 : int ndroppedstats, xl_xact_stats_item *droppedstats,
6046 : int xactflags, TransactionId twophase_xid,
6047 : const char *twophase_gid)
6048 : {
6049 : xl_xact_abort xlrec;
6050 : xl_xact_xinfo xl_xinfo;
6051 : xl_xact_subxacts xl_subxacts;
6052 : xl_xact_relfilelocators xl_relfilelocators;
6053 : xl_xact_stats_items xl_dropped_stats;
6054 : xl_xact_twophase xl_twophase;
6055 : xl_xact_dbinfo xl_dbinfo;
6056 : xl_xact_origin xl_origin;
6057 :
6058 : uint8 info;
6059 :
6060 : Assert(CritSectionCount > 0);
6061 :
6062 9379 : xl_xinfo.xinfo = 0;
6063 :
6064 : /* decide between a plain and 2pc abort */
6065 9379 : if (!TransactionIdIsValid(twophase_xid))
6066 9332 : info = XLOG_XACT_ABORT;
6067 : else
6068 47 : info = XLOG_XACT_ABORT_PREPARED;
6069 :
6070 :
6071 : /* First figure out and collect all the information needed */
6072 :
6073 9379 : xlrec.xact_time = abort_time;
6074 :
6075 9379 : if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
6076 5245 : xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
6077 :
6078 9379 : if (nsubxacts > 0)
6079 : {
6080 107 : xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
6081 107 : xl_subxacts.nsubxacts = nsubxacts;
6082 : }
6083 :
6084 9379 : if (nrels > 0)
6085 : {
6086 1389 : xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
6087 1389 : xl_relfilelocators.nrels = nrels;
6088 1389 : info |= XLR_SPECIAL_REL_UPDATE;
6089 : }
6090 :
6091 9379 : if (ndroppedstats > 0)
6092 : {
6093 1965 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
6094 1965 : xl_dropped_stats.nitems = ndroppedstats;
6095 : }
6096 :
6097 9379 : if (TransactionIdIsValid(twophase_xid))
6098 : {
6099 47 : xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
6100 47 : xl_twophase.xid = twophase_xid;
6101 : Assert(twophase_gid != NULL);
6102 :
6103 47 : if (XLogLogicalInfoActive())
6104 13 : xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
6105 : }
6106 :
6107 9379 : if (TransactionIdIsValid(twophase_xid) && XLogLogicalInfoActive())
6108 : {
6109 13 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
6110 13 : xl_dbinfo.dbId = MyDatabaseId;
6111 13 : xl_dbinfo.tsId = MyDatabaseTableSpace;
6112 : }
6113 :
6114 : /*
6115 : * Dump transaction origin information. We need this during recovery to
6116 : * update the replication origin progress.
6117 : */
6118 9379 : if (replorigin_xact_state.origin != InvalidReplOriginId)
6119 : {
6120 29 : xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
6121 :
6122 29 : xl_origin.origin_lsn = replorigin_xact_state.origin_lsn;
6123 29 : xl_origin.origin_timestamp = replorigin_xact_state.origin_timestamp;
6124 : }
6125 :
6126 9379 : if (xl_xinfo.xinfo != 0)
6127 5500 : info |= XLOG_XACT_HAS_INFO;
6128 :
6129 : /* Then include all the collected data into the abort record. */
6130 :
6131 9379 : XLogBeginInsert();
6132 :
6133 9379 : XLogRegisterData(&xlrec, MinSizeOfXactAbort);
6134 :
6135 9379 : if (xl_xinfo.xinfo != 0)
6136 5500 : XLogRegisterData(&xl_xinfo, sizeof(xl_xinfo));
6137 :
6138 9379 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
6139 13 : XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo));
6140 :
6141 9379 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
6142 : {
6143 107 : XLogRegisterData(&xl_subxacts,
6144 : MinSizeOfXactSubxacts);
6145 107 : XLogRegisterData(subxacts,
6146 : nsubxacts * sizeof(TransactionId));
6147 : }
6148 :
6149 9379 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
6150 : {
6151 1389 : XLogRegisterData(&xl_relfilelocators,
6152 : MinSizeOfXactRelfileLocators);
6153 1389 : XLogRegisterData(rels,
6154 : nrels * sizeof(RelFileLocator));
6155 : }
6156 :
6157 9379 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
6158 : {
6159 1965 : XLogRegisterData(&xl_dropped_stats,
6160 : MinSizeOfXactStatsItems);
6161 1965 : XLogRegisterData(droppedstats,
6162 : ndroppedstats * sizeof(xl_xact_stats_item));
6163 : }
6164 :
6165 9379 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
6166 : {
6167 47 : XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase));
6168 47 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
6169 13 : XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1);
6170 : }
6171 :
6172 9379 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
6173 29 : XLogRegisterData(&xl_origin, sizeof(xl_xact_origin));
6174 :
6175 : /* Include the replication origin */
6176 9379 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
6177 :
6178 9379 : return XLogInsert(RM_XACT_ID, info);
6179 : }
6180 :
6181 : /*
6182 : * Before 9.0 this was a fairly short function, but now it performs many
6183 : * actions for which the order of execution is critical.
6184 : */
6185 : static void
6186 23877 : xact_redo_commit(xl_xact_parsed_commit *parsed,
6187 : TransactionId xid,
6188 : XLogRecPtr lsn,
6189 : ReplOriginId origin_id)
6190 : {
6191 : TransactionId max_xid;
6192 : TimestampTz commit_time;
6193 :
6194 : Assert(TransactionIdIsValid(xid));
6195 :
6196 23877 : max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
6197 :
6198 : /* Make sure nextXid is beyond any XID mentioned in the record. */
6199 23877 : AdvanceNextFullTransactionIdPastXid(max_xid);
6200 :
6201 : Assert(((parsed->xinfo & XACT_XINFO_HAS_ORIGIN) == 0) ==
6202 : (origin_id == InvalidReplOriginId));
6203 :
6204 23877 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6205 20 : commit_time = parsed->origin_timestamp;
6206 : else
6207 23857 : commit_time = parsed->xact_time;
6208 :
6209 : /* Set the transaction commit timestamp and metadata */
6210 23877 : TransactionTreeSetCommitTsData(xid, parsed->nsubxacts, parsed->subxacts,
6211 : commit_time, origin_id);
6212 :
6213 23877 : if (standbyState == STANDBY_DISABLED)
6214 : {
6215 : /*
6216 : * Mark the transaction committed in pg_xact.
6217 : */
6218 2228 : TransactionIdCommitTree(xid, parsed->nsubxacts, parsed->subxacts);
6219 : }
6220 : else
6221 : {
6222 : /*
6223 : * If a transaction completion record arrives that has as-yet
6224 : * unobserved subtransactions then this will not have been fully
6225 : * handled by the call to RecordKnownAssignedTransactionIds() in the
6226 : * main recovery loop in xlog.c. So we need to do bookkeeping again to
6227 : * cover that case. This is confusing and it is easy to think this
6228 : * call is irrelevant, which has happened three times in development
6229 : * already. Leave it in.
6230 : */
6231 21649 : RecordKnownAssignedTransactionIds(max_xid);
6232 :
6233 : /*
6234 : * Mark the transaction committed in pg_xact. We use async commit
6235 : * protocol during recovery to provide information on database
6236 : * consistency for when users try to set hint bits. It is important
6237 : * that we do not set hint bits until the minRecoveryPoint is past
6238 : * this commit record. This ensures that if we crash we don't see hint
6239 : * bits set on changes made by transactions that haven't yet
6240 : * recovered. It's unlikely but it's good to be safe.
6241 : */
6242 21649 : TransactionIdAsyncCommitTree(xid, parsed->nsubxacts, parsed->subxacts, lsn);
6243 :
6244 : /*
6245 : * We must mark clog before we update the ProcArray.
6246 : */
6247 21649 : ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
6248 :
6249 : /*
6250 : * Send any cache invalidations attached to the commit. We must
6251 : * maintain the same order of invalidation then release locks as
6252 : * occurs in CommitTransaction().
6253 : */
6254 21649 : ProcessCommittedInvalidationMessages(parsed->msgs, parsed->nmsgs,
6255 21649 : XactCompletionRelcacheInitFileInval(parsed->xinfo),
6256 : parsed->dbId, parsed->tsId);
6257 :
6258 : /*
6259 : * Release locks, if any. We do this for both two phase and normal one
6260 : * phase transactions. In effect we are ignoring the prepare phase and
6261 : * just going straight to lock release.
6262 : */
6263 21649 : if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
6264 10591 : StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
6265 : }
6266 :
6267 23877 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6268 : {
6269 : /* recover apply progress */
6270 20 : replorigin_advance(origin_id, parsed->origin_lsn, lsn,
6271 : false /* backward */ , false /* WAL */ );
6272 : }
6273 :
6274 : /* Make sure files supposed to be dropped are dropped */
6275 23877 : if (parsed->nrels > 0)
6276 : {
6277 : /*
6278 : * First update minimum recovery point to cover this WAL record. Once
6279 : * a relation is deleted, there's no going back. The buffer manager
6280 : * enforces the WAL-first rule for normal updates to relation files,
6281 : * so that the minimum recovery point is always updated before the
6282 : * corresponding change in the data file is flushed to disk, but we
6283 : * have to do the same here since we're bypassing the buffer manager.
6284 : *
6285 : * Doing this before deleting the files means that if a deletion fails
6286 : * for some reason, you cannot start up the system even after restart,
6287 : * until you fix the underlying situation so that the deletion will
6288 : * succeed. Alternatively, we could update the minimum recovery point
6289 : * after deletion, but that would leave a small window where the
6290 : * WAL-first rule would be violated.
6291 : */
6292 2288 : XLogFlush(lsn);
6293 :
6294 : /* Make sure files supposed to be dropped are dropped */
6295 2288 : DropRelationFiles(parsed->xlocators, parsed->nrels, true);
6296 : }
6297 :
6298 23877 : if (parsed->nstats > 0)
6299 : {
6300 : /* see equivalent call for relations above */
6301 2964 : XLogFlush(lsn);
6302 :
6303 2964 : pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
6304 : }
6305 :
6306 : /*
6307 : * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
6308 : * in normal operation. For example, in CREATE DATABASE, we copy all files
6309 : * from the template database, and then commit the transaction. If we
6310 : * crash after all the files have been copied but before the commit, you
6311 : * have files in the data directory without an entry in pg_database. To
6312 : * minimize the window for that, we use ForceSyncCommit() to rush the
6313 : * commit record to disk as quick as possible. We have the same window
6314 : * during recovery, and forcing an XLogFlush() (which updates
6315 : * minRecoveryPoint during recovery) helps to reduce that problem window,
6316 : * for any user that requested ForceSyncCommit().
6317 : */
6318 23877 : if (XactCompletionForceSyncCommit(parsed->xinfo))
6319 49 : XLogFlush(lsn);
6320 :
6321 : /*
6322 : * If asked by the primary (because someone is waiting for a synchronous
6323 : * commit = remote_apply), we will need to ask walreceiver to send a reply
6324 : * immediately.
6325 : */
6326 23877 : if (XactCompletionApplyFeedback(parsed->xinfo))
6327 2 : XLogRequestWalReceiverReply();
6328 23877 : }
6329 :
6330 : /*
6331 : * Be careful with the order of execution, as with xact_redo_commit().
6332 : * The two functions are similar but differ in key places.
6333 : *
6334 : * Note also that an abort can be for a subtransaction and its children,
6335 : * not just for a top level abort. That means we have to consider
6336 : * topxid != xid, whereas in commit we would find topxid == xid always
6337 : * because subtransaction commit is never WAL logged.
6338 : */
6339 : static void
6340 2003 : xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid,
6341 : XLogRecPtr lsn, ReplOriginId origin_id)
6342 : {
6343 : TransactionId max_xid;
6344 :
6345 : Assert(TransactionIdIsValid(xid));
6346 :
6347 : /* Make sure nextXid is beyond any XID mentioned in the record. */
6348 2003 : max_xid = TransactionIdLatest(xid,
6349 : parsed->nsubxacts,
6350 2003 : parsed->subxacts);
6351 2003 : AdvanceNextFullTransactionIdPastXid(max_xid);
6352 :
6353 2003 : if (standbyState == STANDBY_DISABLED)
6354 : {
6355 : /* Mark the transaction aborted in pg_xact, no need for async stuff */
6356 20 : TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
6357 : }
6358 : else
6359 : {
6360 : /*
6361 : * If a transaction completion record arrives that has as-yet
6362 : * unobserved subtransactions then this will not have been fully
6363 : * handled by the call to RecordKnownAssignedTransactionIds() in the
6364 : * main recovery loop in xlog.c. So we need to do bookkeeping again to
6365 : * cover that case. This is confusing and it is easy to think this
6366 : * call is irrelevant, which has happened three times in development
6367 : * already. Leave it in.
6368 : */
6369 1983 : RecordKnownAssignedTransactionIds(max_xid);
6370 :
6371 : /* Mark the transaction aborted in pg_xact, no need for async stuff */
6372 1983 : TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
6373 :
6374 : /*
6375 : * We must update the ProcArray after we have marked clog.
6376 : */
6377 1983 : ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
6378 :
6379 : /*
6380 : * There are no invalidation messages to send or undo.
6381 : */
6382 :
6383 : /*
6384 : * Release locks, if any. There are no invalidations to send.
6385 : */
6386 1983 : if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
6387 1259 : StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
6388 : }
6389 :
6390 2003 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6391 : {
6392 : /* recover apply progress */
6393 5 : replorigin_advance(origin_id, parsed->origin_lsn, lsn,
6394 : false /* backward */ , false /* WAL */ );
6395 : }
6396 :
6397 : /* Make sure files supposed to be dropped are dropped */
6398 2003 : if (parsed->nrels > 0)
6399 : {
6400 : /*
6401 : * See comments about update of minimum recovery point on truncation,
6402 : * in xact_redo_commit().
6403 : */
6404 334 : XLogFlush(lsn);
6405 :
6406 334 : DropRelationFiles(parsed->xlocators, parsed->nrels, true);
6407 : }
6408 :
6409 2003 : if (parsed->nstats > 0)
6410 : {
6411 : /* see equivalent call for relations above */
6412 460 : XLogFlush(lsn);
6413 :
6414 460 : pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
6415 : }
6416 2003 : }
6417 :
6418 : void
6419 26235 : xact_redo(XLogReaderState *record)
6420 : {
6421 26235 : uint8 info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
6422 :
6423 : /* Backup blocks are not used in xact records */
6424 : Assert(!XLogRecHasAnyBlockRefs(record));
6425 :
6426 26235 : if (info == XLOG_XACT_COMMIT)
6427 : {
6428 23831 : xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
6429 : xl_xact_parsed_commit parsed;
6430 :
6431 23831 : ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
6432 23831 : xact_redo_commit(&parsed, XLogRecGetXid(record),
6433 23831 : record->EndRecPtr, XLogRecGetOrigin(record));
6434 : }
6435 2404 : else if (info == XLOG_XACT_COMMIT_PREPARED)
6436 : {
6437 46 : xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
6438 : xl_xact_parsed_commit parsed;
6439 :
6440 46 : ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
6441 46 : xact_redo_commit(&parsed, parsed.twophase_xid,
6442 46 : record->EndRecPtr, XLogRecGetOrigin(record));
6443 :
6444 : /* Delete TwoPhaseState gxact entry and/or 2PC file. */
6445 46 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
6446 46 : PrepareRedoRemove(parsed.twophase_xid, false);
6447 46 : LWLockRelease(TwoPhaseStateLock);
6448 : }
6449 2358 : else if (info == XLOG_XACT_ABORT)
6450 : {
6451 1978 : xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
6452 : xl_xact_parsed_abort parsed;
6453 :
6454 1978 : ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
6455 1978 : xact_redo_abort(&parsed, XLogRecGetXid(record),
6456 1978 : record->EndRecPtr, XLogRecGetOrigin(record));
6457 : }
6458 380 : else if (info == XLOG_XACT_ABORT_PREPARED)
6459 : {
6460 25 : xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
6461 : xl_xact_parsed_abort parsed;
6462 :
6463 25 : ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
6464 25 : xact_redo_abort(&parsed, parsed.twophase_xid,
6465 25 : record->EndRecPtr, XLogRecGetOrigin(record));
6466 :
6467 : /* Delete TwoPhaseState gxact entry and/or 2PC file. */
6468 25 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
6469 25 : PrepareRedoRemove(parsed.twophase_xid, false);
6470 25 : LWLockRelease(TwoPhaseStateLock);
6471 : }
6472 355 : else if (info == XLOG_XACT_PREPARE)
6473 : {
6474 : /*
6475 : * Store xid and start/end pointers of the WAL record in TwoPhaseState
6476 : * gxact entry.
6477 : */
6478 81 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
6479 81 : PrepareRedoAdd(InvalidFullTransactionId,
6480 81 : XLogRecGetData(record),
6481 : record->ReadRecPtr,
6482 : record->EndRecPtr,
6483 81 : XLogRecGetOrigin(record));
6484 81 : LWLockRelease(TwoPhaseStateLock);
6485 : }
6486 274 : else if (info == XLOG_XACT_ASSIGNMENT)
6487 : {
6488 21 : xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record);
6489 :
6490 21 : if (standbyState >= STANDBY_INITIALIZED)
6491 21 : ProcArrayApplyXidAssignment(xlrec->xtop,
6492 21 : xlrec->nsubxacts, xlrec->xsub);
6493 : }
6494 253 : else if (info == XLOG_XACT_INVALIDATIONS)
6495 : {
6496 : /*
6497 : * XXX we do ignore this for now, what matters are invalidations
6498 : * written into the commit record.
6499 : */
6500 : }
6501 : else
6502 0 : elog(PANIC, "xact_redo: unknown op code %u", info);
6503 26235 : }
|