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