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