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