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