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