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 : : 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 : 1253017 : IsTransactionState(void)
391 : : {
392 : 1253017 : 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 : 1253017 : 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 : 951940 : IsAbortedTransactionBlockState(void)
411 : : {
412 : 951940 : TransactionState s = CurrentTransactionState;
413 : :
414 [ + + ]: 951940 : if (s->blockState == TBLOCK_ABORT ||
415 [ + + ]: 950012 : s->blockState == TBLOCK_SUBABORT)
416 : 2382 : return true;
417 : :
418 : 949558 : 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 : 34451 : GetTopTransactionId(void)
430 : : {
431 [ + + ]: 34451 : if (!FullTransactionIdIsValid(XactTopFullTransactionId))
432 : 696 : AssignTransactionId(&TopTransactionStateData);
433 : 34451 : 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 : 66787316 : GetTopTransactionIdIfAny(void)
445 : : {
446 : 66787316 : 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 : 17273900 : GetCurrentTransactionId(void)
458 : : {
459 : 17273900 : TransactionState s = CurrentTransactionState;
460 : :
461 [ + + ]: 17273900 : if (!FullTransactionIdIsValid(s->fullTransactionId))
462 : 178319 : AssignTransactionId(s);
463 : 17273893 : 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 : 25246428 : GetCurrentTransactionIdIfAny(void)
475 : : {
476 : 25246428 : 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 : 3205 : GetTopFullTransactionId(void)
487 : : {
488 [ + + ]: 3205 : if (!FullTransactionIdIsValid(XactTopFullTransactionId))
489 : 2116 : AssignTransactionId(&TopTransactionStateData);
490 : 3205 : 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 : 395 : GetCurrentFullTransactionId(void)
516 : : {
517 : 395 : TransactionState s = CurrentTransactionState;
518 : :
519 [ + + ]: 395 : if (!FullTransactionIdIsValid(s->fullTransactionId))
520 : 15 : AssignTransactionId(s);
521 : 395 : 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 : 25192541 : MarkCurrentTransactionIdLoggedIfAny(void)
545 : : {
546 [ + + ]: 25192541 : if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId))
547 : 24822900 : CurrentTransactionState->didLogXid = true;
548 : 25192541 : }
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 : 25201796 : IsSubxactTopXidLogPending(void)
563 : : {
564 : : /* check whether it is already logged */
565 [ + + ]: 25201796 : if (CurrentTransactionState->topXidLogged)
566 : 102132 : return false;
567 : :
568 : : /* effective_wal_level has to be logical */
569 [ + + + + ]: 25099664 : if (!XLogLogicalInfoActive())
570 : 24496659 : return false;
571 : :
572 : : /* we need to be in a transaction state */
573 [ + + ]: 603005 : if (!IsTransactionState())
574 : 4405 : return false;
575 : :
576 : : /* it has to be a subtransaction */
577 [ + + ]: 598600 : if (!IsSubTransaction())
578 : 598366 : return false;
579 : :
580 : : /* the subtransaction has to have a XID assigned */
581 [ + + ]: 234 : if (!TransactionIdIsValid(GetCurrentTransactionIdIfAny()))
582 : 8 : return false;
583 : :
584 : 226 : 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 : 224 : MarkSubxactTopXidLogged(void)
595 : : {
596 : : Assert(IsSubxactTopXidLogPending());
597 : :
598 : 224 : CurrentTransactionState->topXidLogged = true;
599 : 224 : }
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 : 182366 : AssignTransactionId(TransactionState s)
639 : : {
640 : 182366 : bool isSubXact = (s->parent != NULL);
641 : : ResourceOwner currentOwner;
642 : 182366 : 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 [ + - - + ]: 182366 : 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 [ + + + + ]: 182366 : if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId))
664 : : {
665 : 627 : TransactionState p = s->parent;
666 : : TransactionState *parents;
667 : 627 : size_t parentOffset = 0;
668 : :
669 : 627 : parents = palloc_array(TransactionState, s->nestingLevel);
670 [ + + + + ]: 1847 : while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
671 : : {
672 : 1220 : parents[parentOffset++] = p;
673 : 1220 : 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 [ + + ]: 1847 : while (parentOffset != 0)
681 : 1220 : AssignTransactionId(parents[--parentOffset]);
682 : :
683 : 627 : 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 [ + + + + : 182366 : if (isSubXact && XLogLogicalInfoActive() &&
+ + ]
697 [ + + ]: 305 : !TopTransactionStateData.didLogXid)
698 : 26 : 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 : 182366 : s->fullTransactionId = GetNewTransactionId(isSubXact);
710 [ + + ]: 182359 : if (!isSubXact)
711 : 166004 : XactTopFullTransactionId = s->fullTransactionId;
712 : :
713 [ + + ]: 182359 : if (isSubXact)
714 : 16355 : SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),
715 : 16355 : 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 [ + + ]: 182359 : if (!isSubXact)
722 : 166004 : 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 : 182359 : currentOwner = CurrentResourceOwner;
730 : 182359 : CurrentResourceOwner = s->curTransactionOwner;
731 : :
732 : 182359 : XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));
733 : :
734 : 182359 : 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 [ + + + + ]: 182359 : if (isSubXact && XLogStandbyInfoActive())
755 : : {
756 : 16086 : unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);
757 : 16086 : nUnreportedXids++;
758 : :
759 : : /*
760 : : * ensure this test matches similar one in
761 : : * RecoverPreparedTransactions()
762 : : */
763 [ + + + + ]: 16086 : 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 : 252 : xlrec.xtop = GetTopTransactionId();
773 : : Assert(TransactionIdIsValid(xlrec.xtop));
774 : 252 : xlrec.nsubxacts = nUnreportedXids;
775 : :
776 : 252 : XLogBeginInsert();
777 : 252 : XLogRegisterData(&xlrec, MinSizeOfXactAssignment);
778 : 252 : XLogRegisterData(unreportedXids,
779 : : nUnreportedXids * sizeof(TransactionId));
780 : :
781 : 252 : (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
782 : :
783 : 252 : nUnreportedXids = 0;
784 : : /* mark top, not current xact as having been logged */
785 : 252 : TopTransactionStateData.didLogXid = true;
786 : : }
787 : : }
788 : 182359 : }
789 : :
790 : : /*
791 : : * GetCurrentSubTransactionId
792 : : */
793 : : SubTransactionId
794 : 9365900 : GetCurrentSubTransactionId(void)
795 : : {
796 : 9365900 : TransactionState s = CurrentTransactionState;
797 : :
798 : 9365900 : 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 : 7988692 : GetCurrentCommandId(bool used)
833 : : {
834 : : /* this is global to a transaction, not subtransaction-local */
835 [ + + ]: 7988692 : 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 [ - + ]: 4368998 : if (IsParallelWorker())
844 [ # # ]: 0 : ereport(ERROR,
845 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
846 : : errmsg("cannot modify data in a parallel worker")));
847 : :
848 : 4368998 : currentCommandIdUsed = true;
849 : : }
850 : 7988692 : 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 : 1995 : SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
863 : : {
864 : : Assert(IsParallelWorker());
865 : 1995 : xactStartTimestamp = xact_ts;
866 : 1995 : stmtStartTimestamp = stmt_ts;
867 : 1995 : }
868 : :
869 : : /*
870 : : * GetCurrentTransactionStartTimestamp
871 : : */
872 : : TimestampTz
873 : 45304 : GetCurrentTransactionStartTimestamp(void)
874 : : {
875 : 45304 : return xactStartTimestamp;
876 : : }
877 : :
878 : : /*
879 : : * GetCurrentStatementStartTimestamp
880 : : */
881 : : TimestampTz
882 : 1524662 : GetCurrentStatementStartTimestamp(void)
883 : : {
884 : 1524662 : 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 : 1284717 : GetCurrentTransactionStopTimestamp(void)
895 : : {
896 : 1284717 : 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 [ + + ]: 1284717 : if (xactStopTimestamp == 0)
905 : 377860 : xactStopTimestamp = GetCurrentTimestamp();
906 : :
907 : 1284717 : 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 : 767784 : SetCurrentStatementStartTimestamp(void)
918 : : {
919 [ + + ]: 767784 : if (!IsParallelWorker())
920 : 765789 : stmtStartTimestamp = GetCurrentTimestamp();
921 : : else
922 : : Assert(stmtStartTimestamp != 0);
923 : 767784 : }
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 : 26637979 : GetCurrentTransactionNestLevel(void)
933 : : {
934 : 26637979 : TransactionState s = CurrentTransactionState;
935 : :
936 : 26637979 : return s->nestingLevel;
937 : : }
938 : :
939 : :
940 : : /*
941 : : * TransactionIdIsCurrentTransactionId
942 : : */
943 : : bool
944 : 66764935 : 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 [ + + ]: 66764935 : if (!TransactionIdIsNormal(xid))
962 : 757701 : return false;
963 : :
964 [ + + ]: 66007234 : if (TransactionIdEquals(xid, GetTopTransactionIdIfAny()))
965 : 38049391 : 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 [ + + ]: 27957843 : if (nParallelCurrentXids > 0)
974 : : {
975 : : int low,
976 : : high;
977 : :
978 : 2476627 : low = 0;
979 : 2476627 : high = nParallelCurrentXids - 1;
980 [ + + ]: 9720337 : while (low <= high)
981 : : {
982 : : int middle;
983 : : TransactionId probe;
984 : :
985 : 9627315 : middle = low + (high - low) / 2;
986 : 9627315 : probe = ParallelCurrentXids[middle];
987 [ + + ]: 9627315 : if (probe == xid)
988 : 2383605 : return true;
989 [ + + ]: 7243710 : else if (probe < xid)
990 : 7150702 : low = middle + 1;
991 : : else
992 : 93008 : high = middle - 1;
993 : : }
994 : 93022 : 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 [ + + ]: 50924503 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
1005 : : {
1006 : : int low,
1007 : : high;
1008 : :
1009 [ - + ]: 25562748 : if (s->state == TRANS_ABORT)
1010 : 0 : continue;
1011 [ + + ]: 25562748 : if (!FullTransactionIdIsValid(s->fullTransactionId))
1012 : 12406255 : continue; /* it can't have any child XIDs either */
1013 [ + + ]: 13156493 : if (TransactionIdEquals(xid, XidFromFullTransactionId(s->fullTransactionId)))
1014 : 117902 : return true;
1015 : : /* As the childXids array is ordered, we can use binary search */
1016 : 13038591 : low = 0;
1017 : 13038591 : high = s->nChildXids - 1;
1018 [ + + ]: 13039467 : while (low <= high)
1019 : : {
1020 : : int middle;
1021 : : TransactionId probe;
1022 : :
1023 : 2435 : middle = low + (high - low) / 2;
1024 : 2435 : probe = s->childXids[middle];
1025 [ + + ]: 2435 : if (TransactionIdEquals(probe, xid))
1026 : 1559 : return true;
1027 [ + + ]: 876 : else if (TransactionIdPrecedes(probe, xid))
1028 : 803 : low = middle + 1;
1029 : : else
1030 : 73 : high = middle - 1;
1031 : : }
1032 : : }
1033 : :
1034 : 25361755 : 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 : 10199926 : TransactionStartedDuringRecovery(void)
1046 : : {
1047 : 10199926 : 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 : 4635 : EnterParallelMode(void)
1083 : : {
1084 : 4635 : TransactionState s = CurrentTransactionState;
1085 : :
1086 : : Assert(s->parallelModeLevel >= 0);
1087 : :
1088 : 4635 : ++s->parallelModeLevel;
1089 : 4635 : }
1090 : :
1091 : : /*
1092 : : * ExitParallelMode
1093 : : */
1094 : : void
1095 : 2632 : ExitParallelMode(void)
1096 : : {
1097 : 2632 : TransactionState s = CurrentTransactionState;
1098 : :
1099 : : Assert(s->parallelModeLevel > 0);
1100 : : Assert(s->parallelModeLevel > 1 || s->parallelChildXact ||
1101 : : !ParallelContextActive());
1102 : :
1103 : 2632 : --s->parallelModeLevel;
1104 : 2632 : }
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 : 32160294 : IsInParallelMode(void)
1121 : : {
1122 : 32160294 : TransactionState s = CurrentTransactionState;
1123 : :
1124 [ + + + + ]: 32160294 : return s->parallelModeLevel != 0 || s->parallelChildXact;
1125 : : }
1126 : :
1127 : : /*
1128 : : * CommandCounterIncrement
1129 : : */
1130 : : void
1131 : 1957026 : 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 [ + + ]: 1957026 : 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 [ + - - + ]: 724417 : if (IsInParallelMode() || IsParallelWorker())
1147 [ # # ]: 0 : ereport(ERROR,
1148 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
1149 : : errmsg("cannot start commands during a parallel operation")));
1150 : :
1151 : 724417 : currentCommandId += 1;
1152 [ - + ]: 724417 : 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 : 724417 : currentCommandIdUsed = false;
1160 : :
1161 : : /* Propagate new command ID into static snapshots */
1162 : 724417 : 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 : 724417 : AtCCI_LocalCache();
1171 : : }
1172 : 1957022 : }
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 : 597 : ForceSyncCommit(void)
1184 : : {
1185 : 597 : forceSyncCommit = true;
1186 : 597 : }
1187 : :
1188 : :
1189 : : /* ----------------------------------------------------------------
1190 : : * StartTransaction stuff
1191 : : * ----------------------------------------------------------------
1192 : : */
1193 : :
1194 : : /*
1195 : : * AtStart_Cache
1196 : : */
1197 : : static void
1198 : 649978 : AtStart_Cache(void)
1199 : : {
1200 : 649978 : AcceptInvalidationMessages();
1201 : 649978 : }
1202 : :
1203 : : /*
1204 : : * AtStart_Memory
1205 : : */
1206 : : static void
1207 : 649978 : AtStart_Memory(void)
1208 : : {
1209 : 649978 : TransactionState s = CurrentTransactionState;
1210 : :
1211 : : /*
1212 : : * Remember the memory context that was active prior to transaction start.
1213 : : */
1214 : 649978 : 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 [ + + ]: 649978 : if (TransactionAbortContext == NULL)
1224 : 21105 : TransactionAbortContext =
1225 : 21105 : 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 [ + + ]: 649978 : if (TopTransactionContext == NULL)
1237 : 21105 : TopTransactionContext =
1238 : 21105 : 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 : 649978 : CurTransactionContext = TopTransactionContext;
1247 : 649978 : s->curTransactionContext = CurTransactionContext;
1248 : :
1249 : : /* Make the CurTransactionContext active. */
1250 : 649978 : MemoryContextSwitchTo(CurTransactionContext);
1251 : 649978 : }
1252 : :
1253 : : /*
1254 : : * AtStart_ResourceOwner
1255 : : */
1256 : : static void
1257 : 649978 : AtStart_ResourceOwner(void)
1258 : : {
1259 : 649978 : 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 : 649978 : s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
1270 : :
1271 : 649978 : TopTransactionResourceOwner = s->curTransactionOwner;
1272 : 649978 : CurTransactionResourceOwner = s->curTransactionOwner;
1273 : 649978 : CurrentResourceOwner = s->curTransactionOwner;
1274 : 649978 : }
1275 : :
1276 : : /* ----------------------------------------------------------------
1277 : : * StartSubTransaction stuff
1278 : : * ----------------------------------------------------------------
1279 : : */
1280 : :
1281 : : /*
1282 : : * AtSubStart_Memory
1283 : : */
1284 : : static void
1285 : 22857 : AtSubStart_Memory(void)
1286 : : {
1287 : 22857 : TransactionState s = CurrentTransactionState;
1288 : :
1289 : : Assert(CurTransactionContext != NULL);
1290 : :
1291 : : /*
1292 : : * Remember the context that was active prior to subtransaction start.
1293 : : */
1294 : 22857 : 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 : 22857 : CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
1302 : : "CurTransactionContext",
1303 : : ALLOCSET_DEFAULT_SIZES);
1304 : 22857 : s->curTransactionContext = CurTransactionContext;
1305 : :
1306 : : /* Make the CurTransactionContext active. */
1307 : 22857 : MemoryContextSwitchTo(CurTransactionContext);
1308 : 22857 : }
1309 : :
1310 : : /*
1311 : : * AtSubStart_ResourceOwner
1312 : : */
1313 : : static void
1314 : 22857 : AtSubStart_ResourceOwner(void)
1315 : : {
1316 : 22857 : 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 : 22857 : s->curTransactionOwner =
1325 : 22857 : ResourceOwnerCreate(s->parent->curTransactionOwner,
1326 : : "SubTransaction");
1327 : :
1328 : 22857 : CurTransactionResourceOwner = s->curTransactionOwner;
1329 : 22857 : CurrentResourceOwner = s->curTransactionOwner;
1330 : 22857 : }
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 : 611732 : RecordTransactionCommit(void)
1347 : : {
1348 : 611732 : TransactionId xid = GetTopTransactionIdIfAny();
1349 : 611732 : bool markXidCommitted = TransactionIdIsValid(xid);
1350 : 611732 : TransactionId latestXid = InvalidTransactionId;
1351 : : int nrels;
1352 : : RelFileLocator *rels;
1353 : : int nchildren;
1354 : : TransactionId *children;
1355 : 611732 : int ndroppedstats = 0;
1356 : 611732 : xl_xact_stats_item *droppedstats = NULL;
1357 : 611732 : int nmsgs = 0;
1358 : 611732 : SharedInvalidationMessage *invalMessages = NULL;
1359 : 611732 : 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 [ + + + + ]: 611732 : if (XLogLogicalInfoActive())
1370 : 15121 : LogLogicalInvalidations();
1371 : :
1372 : : /* Get data needed for commit record */
1373 : 611732 : nrels = smgrGetPendingDeletes(true, &rels);
1374 : 611732 : nchildren = xactGetCommittedChildren(&children);
1375 : 611732 : ndroppedstats = pgstat_get_transactional_drops(true, &droppedstats);
1376 [ + + ]: 611732 : if (XLogStandbyInfoActive())
1377 : 327061 : nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
1378 : : &RelcacheInitFileInval);
1379 : 611732 : wrote_xlog = (XactLastRecEnd != 0);
1380 : :
1381 : : /* Load the injection point before entering the critical section */
1382 : 611732 : 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 [ + + ]: 611732 : 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 [ + - - + ]: 454438 : 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 [ + + ]: 454438 : if (nmsgs != 0)
1426 : : {
1427 : 11270 : LogStandbyInvalidations(nmsgs, invalMessages,
1428 : : RelcacheInitFileInval);
1429 : 11270 : 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 [ + + ]: 454438 : if (!wrote_xlog)
1439 : 408003 : 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 [ + + ]: 158386 : replorigin = (replorigin_xact_state.origin != InvalidReplOriginId &&
1450 [ + - ]: 1092 : 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 : 157294 : START_CRIT_SECTION();
1475 : 157294 : 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 : 157294 : pg_write_barrier();
1484 : :
1485 : : /*
1486 : : * Insert the commit XLOG record.
1487 : : */
1488 : 157294 : XactLogCommitRecord(GetCurrentTransactionStopTimestamp(),
1489 : : nchildren, children, nrels, rels,
1490 : : ndroppedstats, droppedstats,
1491 : : nmsgs, invalMessages,
1492 : : RelcacheInitFileInval,
1493 : : MyXactFlags,
1494 : : InvalidTransactionId, NULL /* plain commit */ );
1495 : :
1496 [ + + ]: 157294 : if (replorigin)
1497 : : /* Move LSNs forward for this replication origin */
1498 : 1092 : 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 [ + + + + ]: 157294 : if (!replorigin || replorigin_xact_state.origin_timestamp == 0)
1512 : 156322 : replorigin_xact_state.origin_timestamp = GetCurrentTransactionStopTimestamp();
1513 : :
1514 : 157294 : TransactionTreeSetCommitTsData(xid, nchildren, children,
1515 : : replorigin_xact_state.origin_timestamp,
1516 : 157294 : 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 [ + + + + ]: 203729 : if ((wrote_xlog && markXidCommitted &&
1545 [ + + + + ]: 203729 : synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
1546 [ + + ]: 53710 : forceSyncCommit || nrels > 0)
1547 : : {
1548 : 150040 : 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 : 150040 : 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 [ + - ]: 150040 : if (markXidCommitted)
1560 : 150040 : 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 : 53689 : 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 [ + + ]: 53689 : if (markXidCommitted)
1583 : 7254 : 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 [ + + ]: 203729 : if (markXidCommitted)
1591 : : {
1592 : 157294 : MyProc->delayChkptFlags &= ~DELAY_CHKPT_IN_COMMIT;
1593 : 157294 : END_CRIT_SECTION();
1594 : : }
1595 : :
1596 : : /* Compute latestXid while we have the child XIDs handy */
1597 : 203729 : 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 [ + + + + ]: 203729 : if (wrote_xlog && markXidCommitted)
1609 : 152547 : SyncRepWaitForLSN(XactLastRecEnd, true);
1610 : :
1611 : : /* remember end of last commit record */
1612 : 203729 : XactLastCommitEnd = XactLastRecEnd;
1613 : :
1614 : : /* Reset XactLastRecEnd until the next transaction writes something */
1615 : 203729 : XactLastRecEnd = 0;
1616 : 611732 : cleanup:
1617 : : /* Clean up local data */
1618 [ + + ]: 611732 : if (rels)
1619 : 12243 : pfree(rels);
1620 [ + + ]: 611732 : if (ndroppedstats)
1621 : 14659 : pfree(droppedstats);
1622 : :
1623 : 611732 : return latestXid;
1624 : : }
1625 : :
1626 : :
1627 : : /*
1628 : : * AtCCI_LocalCache
1629 : : */
1630 : : static void
1631 : 724417 : 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 : 724417 : AtCCI_RelationMap();
1639 : :
1640 : : /*
1641 : : * Make catalog changes visible to me for the next command.
1642 : : */
1643 : 724417 : CommandEndInvalidationMessages();
1644 : 724413 : }
1645 : :
1646 : : /*
1647 : : * AtCommit_Memory
1648 : : */
1649 : : static void
1650 : 614048 : AtCommit_Memory(void)
1651 : : {
1652 : 614048 : 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 : 614048 : 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 : 614048 : 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 : 614048 : CurTransactionContext = NULL;
1675 : 614048 : s->curTransactionContext = NULL;
1676 : 614048 : }
1677 : :
1678 : : /* ----------------------------------------------------------------
1679 : : * CommitSubTransaction stuff
1680 : : * ----------------------------------------------------------------
1681 : : */
1682 : :
1683 : : /*
1684 : : * AtSubCommit_Memory
1685 : : */
1686 : : static void
1687 : 17377 : AtSubCommit_Memory(void)
1688 : : {
1689 : 17377 : TransactionState s = CurrentTransactionState;
1690 : :
1691 : : Assert(s->parent != NULL);
1692 : :
1693 : : /* Return to parent transaction level's memory context. */
1694 : 17377 : CurTransactionContext = s->parent->curTransactionContext;
1695 : 17377 : 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 [ + + ]: 17377 : if (MemoryContextIsEmpty(s->curTransactionContext))
1704 : : {
1705 : 17360 : MemoryContextDelete(s->curTransactionContext);
1706 : 17360 : s->curTransactionContext = NULL;
1707 : : }
1708 : 17377 : }
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 : 15466 : AtSubCommit_childXids(void)
1717 : : {
1718 : 15466 : 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 : 15466 : new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
1728 : :
1729 : : /* Allocate or enlarge the parent array if necessary */
1730 [ + + ]: 15466 : 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 : 1722 : new_maxChildXids = Min(new_nChildXids * 2,
1742 : : (int) (MaxAllocSize / sizeof(TransactionId)));
1743 : :
1744 [ - + ]: 1722 : 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 [ + + ]: 1722 : if (s->parent->childXids == NULL)
1756 : : new_childXids =
1757 : 1645 : MemoryContextAlloc(TopTransactionContext,
1758 : : new_maxChildXids * sizeof(TransactionId));
1759 : : else
1760 : 77 : new_childXids = repalloc_array(s->parent->childXids, TransactionId, new_maxChildXids);
1761 : :
1762 : 1722 : s->parent->childXids = new_childXids;
1763 : 1722 : 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 : 15466 : s->parent->childXids[s->parent->nChildXids] = XidFromFullTransactionId(s->fullTransactionId);
1776 : :
1777 [ + + ]: 15466 : 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 : 15466 : s->parent->nChildXids = new_nChildXids;
1783 : :
1784 : : /* Release child's array to avoid leakage */
1785 [ + + ]: 15466 : if (s->childXids != NULL)
1786 : 1018 : pfree(s->childXids);
1787 : : /* We must reset these to avoid double-free if fail later in commit */
1788 : 15466 : s->childXids = NULL;
1789 : 15466 : s->nChildXids = 0;
1790 : 15466 : s->maxChildXids = 0;
1791 : 15466 : }
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 : 41402 : RecordTransactionAbort(bool isSubXact)
1806 : : {
1807 : 41402 : TransactionId xid = GetCurrentTransactionIdIfAny();
1808 : : TransactionId latestXid;
1809 : : int nrels;
1810 : : RelFileLocator *rels;
1811 : 41402 : int ndroppedstats = 0;
1812 : 41402 : 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 [ + + ]: 41402 : if (!TransactionIdIsValid(xid))
1825 : : {
1826 : : /* Reset XactLastRecEnd until the next transaction writes something */
1827 [ + + ]: 32132 : if (!isSubXact)
1828 : 27541 : XactLastRecEnd = 0;
1829 : 32132 : 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 [ - + ]: 9270 : 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 [ + + ]: 9292 : replorigin = (replorigin_xact_state.origin != InvalidReplOriginId &&
1852 [ + - ]: 22 : replorigin_xact_state.origin != DoNotReplicateId);
1853 : :
1854 : : /* Fetch the data we need for the abort record */
1855 : 9270 : nrels = smgrGetPendingDeletes(false, &rels);
1856 : 9270 : nchildren = xactGetCommittedChildren(&children);
1857 : 9270 : ndroppedstats = pgstat_get_transactional_drops(false, &droppedstats);
1858 : :
1859 : : /* XXX do we really need a critical section here? */
1860 : 9270 : START_CRIT_SECTION();
1861 : :
1862 : : /* Write the ABORT record */
1863 [ + + ]: 9270 : if (isSubXact)
1864 : 889 : xact_time = GetCurrentTimestamp();
1865 : : else
1866 : : {
1867 : 8381 : xact_time = GetCurrentTransactionStopTimestamp();
1868 : : }
1869 : :
1870 : 9270 : XactLogAbortRecord(xact_time,
1871 : : nchildren, children,
1872 : : nrels, rels,
1873 : : ndroppedstats, droppedstats,
1874 : : MyXactFlags, InvalidTransactionId,
1875 : : NULL);
1876 : :
1877 [ + + ]: 9270 : if (replorigin)
1878 : : /* Move LSNs forward for this replication origin */
1879 : 22 : 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 [ + + ]: 9270 : if (!isSubXact)
1892 : 8381 : 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 : 9270 : TransactionIdAbortTree(xid, nchildren, children);
1903 : :
1904 : 9270 : END_CRIT_SECTION();
1905 : :
1906 : : /* Compute latestXid while we have the child XIDs handy */
1907 : 9270 : 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 [ + + ]: 9270 : if (isSubXact)
1916 : 889 : XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
1917 : :
1918 : : /* Reset XactLastRecEnd until the next transaction writes something */
1919 [ + + ]: 9270 : if (!isSubXact)
1920 : 8381 : XactLastRecEnd = 0;
1921 : :
1922 : : /* And clean up local data */
1923 [ + + ]: 9270 : if (rels)
1924 : 1418 : pfree(rels);
1925 [ + + ]: 9270 : if (ndroppedstats)
1926 : 1985 : pfree(droppedstats);
1927 : :
1928 : 9270 : return latestXid;
1929 : : }
1930 : :
1931 : : /*
1932 : : * AtAbort_Memory
1933 : : */
1934 : : static void
1935 : 57617 : AtAbort_Memory(void)
1936 : : {
1937 : : /*
1938 : : * Switch into TransactionAbortContext, which should have some free space
1939 : : * even if nothing else does. We'll work in this context until we've
1940 : : * finished cleaning up.
1941 : : *
1942 : : * It is barely possible to get here when we've not been able to create
1943 : : * TransactionAbortContext yet; if so use TopMemoryContext.
1944 : : */
1945 [ + - ]: 57617 : if (TransactionAbortContext != NULL)
1946 : 57617 : MemoryContextSwitchTo(TransactionAbortContext);
1947 : : else
1948 : 0 : MemoryContextSwitchTo(TopMemoryContext);
1949 : 57617 : }
1950 : :
1951 : : /*
1952 : : * AtSubAbort_Memory
1953 : : */
1954 : : static void
1955 : 5480 : AtSubAbort_Memory(void)
1956 : : {
1957 : : Assert(TransactionAbortContext != NULL);
1958 : :
1959 : 5480 : MemoryContextSwitchTo(TransactionAbortContext);
1960 : 5480 : }
1961 : :
1962 : :
1963 : : /*
1964 : : * AtAbort_ResourceOwner
1965 : : */
1966 : : static void
1967 : 35930 : AtAbort_ResourceOwner(void)
1968 : : {
1969 : : /*
1970 : : * Make sure we have a valid ResourceOwner, if possible (else it will be
1971 : : * NULL, which is OK)
1972 : : */
1973 : 35930 : CurrentResourceOwner = TopTransactionResourceOwner;
1974 : 35930 : }
1975 : :
1976 : : /*
1977 : : * AtSubAbort_ResourceOwner
1978 : : */
1979 : : static void
1980 : 5480 : AtSubAbort_ResourceOwner(void)
1981 : : {
1982 : 5480 : TransactionState s = CurrentTransactionState;
1983 : :
1984 : : /* Make sure we have a valid ResourceOwner */
1985 : 5480 : CurrentResourceOwner = s->curTransactionOwner;
1986 : 5480 : }
1987 : :
1988 : :
1989 : : /*
1990 : : * AtSubAbort_childXids
1991 : : */
1992 : : static void
1993 : 889 : AtSubAbort_childXids(void)
1994 : : {
1995 : 889 : TransactionState s = CurrentTransactionState;
1996 : :
1997 : : /*
1998 : : * We keep the child-XID arrays in TopTransactionContext (see
1999 : : * AtSubCommit_childXids). This means we'd better free the array
2000 : : * explicitly at abort to avoid leakage.
2001 : : */
2002 [ + + ]: 889 : if (s->childXids != NULL)
2003 : 26 : pfree(s->childXids);
2004 : 889 : s->childXids = NULL;
2005 : 889 : s->nChildXids = 0;
2006 : 889 : s->maxChildXids = 0;
2007 : :
2008 : : /*
2009 : : * We could prune the unreportedXids array here. But we don't bother. That
2010 : : * would potentially reduce number of XLOG_XACT_ASSIGNMENT records but it
2011 : : * would likely introduce more CPU time into the more common paths, so we
2012 : : * choose not to do that.
2013 : : */
2014 : 889 : }
2015 : :
2016 : : /* ----------------------------------------------------------------
2017 : : * CleanupTransaction stuff
2018 : : * ----------------------------------------------------------------
2019 : : */
2020 : :
2021 : : /*
2022 : : * AtCleanup_Memory
2023 : : */
2024 : : static void
2025 : 35930 : AtCleanup_Memory(void)
2026 : : {
2027 : 35930 : TransactionState s = CurrentTransactionState;
2028 : :
2029 : : /* Should be at top level */
2030 : : Assert(s->parent == NULL);
2031 : :
2032 : : /*
2033 : : * Return to the memory context that was current before we started the
2034 : : * transaction. (In principle, this could not be any of the contexts we
2035 : : * are about to delete. If it somehow is, assertions in mcxt.c will
2036 : : * complain.)
2037 : : */
2038 : 35930 : MemoryContextSwitchTo(s->priorContext);
2039 : :
2040 : : /*
2041 : : * Clear the special abort context for next time.
2042 : : */
2043 [ + - ]: 35930 : if (TransactionAbortContext != NULL)
2044 : 35930 : MemoryContextReset(TransactionAbortContext);
2045 : :
2046 : : /*
2047 : : * Release all transaction-local memory, the same as in AtCommit_Memory,
2048 : : * except we must cope with the possibility that we didn't get as far as
2049 : : * creating TopTransactionContext.
2050 : : */
2051 [ + - ]: 35930 : if (TopTransactionContext != NULL)
2052 : 35930 : MemoryContextReset(TopTransactionContext);
2053 : :
2054 : : /*
2055 : : * Clear these pointers as a pro-forma matter. (Notionally, while
2056 : : * TopTransactionContext still exists, it's currently not associated with
2057 : : * this TransactionState struct.)
2058 : : */
2059 : 35930 : CurTransactionContext = NULL;
2060 : 35930 : s->curTransactionContext = NULL;
2061 : 35930 : }
2062 : :
2063 : :
2064 : : /* ----------------------------------------------------------------
2065 : : * CleanupSubTransaction stuff
2066 : : * ----------------------------------------------------------------
2067 : : */
2068 : :
2069 : : /*
2070 : : * AtSubCleanup_Memory
2071 : : */
2072 : : static void
2073 : 5480 : AtSubCleanup_Memory(void)
2074 : : {
2075 : 5480 : TransactionState s = CurrentTransactionState;
2076 : :
2077 : : Assert(s->parent != NULL);
2078 : :
2079 : : /*
2080 : : * Return to the memory context that was current before we started the
2081 : : * subtransaction. (In principle, this could not be any of the contexts
2082 : : * we are about to delete. If it somehow is, assertions in mcxt.c will
2083 : : * complain.)
2084 : : */
2085 : 5480 : MemoryContextSwitchTo(s->priorContext);
2086 : :
2087 : : /* Update CurTransactionContext (might not be same as priorContext) */
2088 : 5480 : CurTransactionContext = s->parent->curTransactionContext;
2089 : :
2090 : : /*
2091 : : * Clear the special abort context for next time.
2092 : : */
2093 [ + - ]: 5480 : if (TransactionAbortContext != NULL)
2094 : 5480 : MemoryContextReset(TransactionAbortContext);
2095 : :
2096 : : /*
2097 : : * Delete the subxact local memory contexts. Its CurTransactionContext can
2098 : : * go too (note this also kills CurTransactionContexts from any children
2099 : : * of the subxact).
2100 : : */
2101 [ + - ]: 5480 : if (s->curTransactionContext)
2102 : 5480 : MemoryContextDelete(s->curTransactionContext);
2103 : 5480 : s->curTransactionContext = NULL;
2104 : 5480 : }
2105 : :
2106 : : /* ----------------------------------------------------------------
2107 : : * interface routines
2108 : : * ----------------------------------------------------------------
2109 : : */
2110 : :
2111 : : /*
2112 : : * StartTransaction
2113 : : */
2114 : : static void
2115 : 649978 : StartTransaction(void)
2116 : : {
2117 : : TransactionState s;
2118 : : VirtualTransactionId vxid;
2119 : :
2120 : : /*
2121 : : * Let's just make sure the state stack is empty
2122 : : */
2123 : 649978 : s = &TopTransactionStateData;
2124 : 649978 : CurrentTransactionState = s;
2125 : :
2126 : : Assert(!FullTransactionIdIsValid(XactTopFullTransactionId));
2127 : :
2128 : : /* check the current transaction state */
2129 : : Assert(s->state == TRANS_DEFAULT);
2130 : :
2131 : : /*
2132 : : * Set the current transaction state information appropriately during
2133 : : * start processing. Note that once the transaction status is switched
2134 : : * this process cannot fail until the user ID and the security context
2135 : : * flags are fetched below.
2136 : : */
2137 : 649978 : s->state = TRANS_START;
2138 : 649978 : s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
2139 : :
2140 : : /* Determine if statements are logged in this transaction */
2141 [ - + ]: 649978 : xact_is_sampled = log_xact_sample_rate != 0 &&
2142 [ # # ]: 0 : (log_xact_sample_rate == 1 ||
2143 [ # # ]: 0 : pg_prng_double(&pg_global_prng_state) <= log_xact_sample_rate);
2144 : :
2145 : : /*
2146 : : * initialize current transaction state fields
2147 : : *
2148 : : * note: prevXactReadOnly is not used at the outermost level
2149 : : */
2150 : 649978 : s->nestingLevel = 1;
2151 : 649978 : s->gucNestLevel = 1;
2152 : 649978 : s->childXids = NULL;
2153 : 649978 : s->nChildXids = 0;
2154 : 649978 : s->maxChildXids = 0;
2155 : :
2156 : : /*
2157 : : * Once the current user ID and the security context flags are fetched,
2158 : : * both will be properly reset even if transaction startup fails.
2159 : : */
2160 : 649978 : GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
2161 : :
2162 : : /* SecurityRestrictionContext should never be set outside a transaction */
2163 : : Assert(s->prevSecContext == 0);
2164 : :
2165 : : /*
2166 : : * Make sure we've reset xact state variables
2167 : : *
2168 : : * If recovery is still in progress, mark this transaction as read-only.
2169 : : * We have lower level defences in XLogInsert and elsewhere to stop us
2170 : : * from modifying data during recovery, but this gives the normal
2171 : : * indication to the user that the transaction is read-only.
2172 : : */
2173 [ + + ]: 649978 : if (RecoveryInProgress())
2174 : : {
2175 : 2608 : s->startedInRecovery = true;
2176 : 2608 : XactReadOnly = true;
2177 : : }
2178 : : else
2179 : : {
2180 : 647370 : s->startedInRecovery = false;
2181 : 647370 : XactReadOnly = DefaultXactReadOnly;
2182 : : }
2183 : 649978 : XactDeferrable = DefaultXactDeferrable;
2184 : 649978 : XactIsoLevel = DefaultXactIsoLevel;
2185 : 649978 : forceSyncCommit = false;
2186 : 649978 : MyXactFlags = 0;
2187 : :
2188 : : /*
2189 : : * reinitialize within-transaction counters
2190 : : */
2191 : 649978 : s->subTransactionId = TopSubTransactionId;
2192 : 649978 : currentSubTransactionId = TopSubTransactionId;
2193 : 649978 : currentCommandId = FirstCommandId;
2194 : 649978 : currentCommandIdUsed = false;
2195 : :
2196 : : /*
2197 : : * initialize reported xid accounting
2198 : : */
2199 : 649978 : nUnreportedXids = 0;
2200 : 649978 : s->didLogXid = false;
2201 : :
2202 : : /*
2203 : : * must initialize resource-management stuff first
2204 : : */
2205 : 649978 : AtStart_Memory();
2206 : 649978 : AtStart_ResourceOwner();
2207 : :
2208 : : /*
2209 : : * Assign a new LocalTransactionId, and combine it with the proc number to
2210 : : * form a virtual transaction id.
2211 : : */
2212 : 649978 : vxid.procNumber = MyProcNumber;
2213 : 649978 : vxid.localTransactionId = GetNextLocalTransactionId();
2214 : :
2215 : : /*
2216 : : * Lock the virtual transaction id before we announce it in the proc array
2217 : : */
2218 : 649978 : VirtualXactLockTableInsert(vxid);
2219 : :
2220 : : /*
2221 : : * Advertise it in the proc array. We assume assignment of
2222 : : * localTransactionId is atomic, and the proc number should be set
2223 : : * already.
2224 : : */
2225 : : Assert(MyProc->vxid.procNumber == vxid.procNumber);
2226 : 649978 : MyProc->vxid.lxid = vxid.localTransactionId;
2227 : :
2228 : : TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
2229 : :
2230 : : /*
2231 : : * set transaction_timestamp() (a/k/a now()). Normally, we want this to
2232 : : * be the same as the first command's statement_timestamp(), so don't do a
2233 : : * fresh GetCurrentTimestamp() call (which'd be expensive anyway). But
2234 : : * for transactions started inside procedures (i.e., nonatomic SPI
2235 : : * contexts), we do need to advance the timestamp. Also, in a parallel
2236 : : * worker, the timestamp should already have been provided by a call to
2237 : : * SetParallelStartTimestamps().
2238 : : */
2239 [ + + ]: 649978 : if (!IsParallelWorker())
2240 : : {
2241 [ + + ]: 643993 : if (!SPI_inside_nonatomic_context())
2242 : 641772 : xactStartTimestamp = stmtStartTimestamp;
2243 : : else
2244 : 2221 : xactStartTimestamp = GetCurrentTimestamp();
2245 : : }
2246 : : else
2247 : : Assert(xactStartTimestamp != 0);
2248 : 649978 : pgstat_report_xact_timestamp(xactStartTimestamp);
2249 : : /* Mark xactStopTimestamp as unset. */
2250 : 649978 : xactStopTimestamp = 0;
2251 : :
2252 : : /*
2253 : : * initialize other subsystems for new transaction
2254 : : */
2255 : 649978 : AtStart_GUC();
2256 : 649978 : AtStart_Cache();
2257 : 649978 : AfterTriggerBeginXact();
2258 : :
2259 : : /*
2260 : : * done with start processing, set current transaction state to "in
2261 : : * progress"
2262 : : */
2263 : 649978 : s->state = TRANS_INPROGRESS;
2264 : :
2265 : : /* Schedule transaction timeout */
2266 [ + + ]: 649978 : if (TransactionTimeout > 0)
2267 : 1 : enable_timeout_after(TRANSACTION_TIMEOUT, TransactionTimeout);
2268 : :
2269 : 649978 : ShowTransactionState("StartTransaction");
2270 : 649978 : }
2271 : :
2272 : :
2273 : : /*
2274 : : * CommitTransaction
2275 : : *
2276 : : * NB: if you change this routine, better look at PrepareTransaction too!
2277 : : */
2278 : : static void
2279 : 614033 : CommitTransaction(void)
2280 : : {
2281 : 614033 : TransactionState s = CurrentTransactionState;
2282 : : TransactionId latestXid;
2283 : : bool is_parallel_worker;
2284 : :
2285 : 614033 : is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
2286 : :
2287 : : /* Enforce parallel mode restrictions during parallel worker commit. */
2288 [ + + ]: 614033 : if (is_parallel_worker)
2289 : 1987 : EnterParallelMode();
2290 : :
2291 : 614033 : ShowTransactionState("CommitTransaction");
2292 : :
2293 : : /*
2294 : : * check the current transaction state
2295 : : */
2296 [ - + ]: 614033 : if (s->state != TRANS_INPROGRESS)
2297 [ # # ]: 0 : elog(WARNING, "CommitTransaction while in %s state",
2298 : : TransStateAsString(s->state));
2299 : : Assert(s->parent == NULL);
2300 : :
2301 : : /*
2302 : : * Do pre-commit processing that involves calling user-defined code, such
2303 : : * as triggers. SECURITY_RESTRICTED_OPERATION contexts must not queue an
2304 : : * action that would run here, because that would bypass the sandbox.
2305 : : * Since closing cursors could queue trigger actions, triggers could open
2306 : : * cursors, etc, we have to keep looping until there's nothing left to do.
2307 : : */
2308 : : for (;;)
2309 : : {
2310 : : /*
2311 : : * Fire all currently pending deferred triggers.
2312 : : */
2313 : 620142 : AfterTriggerFireDeferred();
2314 : :
2315 : : /*
2316 : : * Close open portals (converting holdable ones into static portals).
2317 : : * If there weren't any, we are done ... otherwise loop back to check
2318 : : * if they queued deferred triggers. Lather, rinse, repeat.
2319 : : */
2320 [ + + ]: 619993 : if (!PreCommit_Portals(false))
2321 : 613884 : break;
2322 : : }
2323 : :
2324 : : /*
2325 : : * The remaining actions cannot call any user-defined code, so it's safe
2326 : : * to start shutting down within-transaction services. But note that most
2327 : : * of this stuff could still throw an error, which would switch us into
2328 : : * the transaction-abort path.
2329 : : */
2330 : :
2331 [ + + ]: 613884 : CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
2332 : : : XACT_EVENT_PRE_COMMIT);
2333 : :
2334 : : /*
2335 : : * If this xact has started any unfinished parallel operation, clean up
2336 : : * its workers, warning about leaked resources. (But we don't actually
2337 : : * reset parallelModeLevel till entering TRANS_COMMIT, a bit below. This
2338 : : * keeps parallel mode restrictions active as long as possible in a
2339 : : * parallel worker.)
2340 : : */
2341 : 613883 : AtEOXact_Parallel(true);
2342 [ + + ]: 613883 : if (is_parallel_worker)
2343 : : {
2344 [ - + ]: 1987 : if (s->parallelModeLevel != 1)
2345 [ # # ]: 0 : elog(WARNING, "parallelModeLevel is %d not 1 at end of parallel worker transaction",
2346 : : s->parallelModeLevel);
2347 : : }
2348 : : else
2349 : : {
2350 [ - + ]: 611896 : if (s->parallelModeLevel != 0)
2351 [ # # ]: 0 : elog(WARNING, "parallelModeLevel is %d not 0 at end of transaction",
2352 : : s->parallelModeLevel);
2353 : : }
2354 : :
2355 : : /* Shut down the deferred-trigger manager */
2356 : 613883 : AfterTriggerEndXact(true);
2357 : :
2358 : : /*
2359 : : * Let ON COMMIT management do its thing (must happen after closing
2360 : : * cursors, to avoid dangling-reference problems)
2361 : : */
2362 : 613883 : PreCommit_on_commit_actions();
2363 : :
2364 : : /*
2365 : : * Synchronize files that are created and not WAL-logged during this
2366 : : * transaction. This must happen before AtEOXact_RelationMap(), so that we
2367 : : * don't see committed-but-broken files after a crash.
2368 : : */
2369 : 613879 : smgrDoPendingSyncs(true, is_parallel_worker);
2370 : :
2371 : : /* close large objects before lower-level cleanup */
2372 : 613879 : AtEOXact_LargeObject(true);
2373 : :
2374 : : /*
2375 : : * Insert notifications sent by NOTIFY commands into the queue. This
2376 : : * should be late in the pre-commit sequence to minimize time spent
2377 : : * holding the notify-insertion lock. However, this could result in
2378 : : * creating a snapshot, so we must do it before serializable cleanup.
2379 : : */
2380 : 613879 : PreCommit_Notify();
2381 : :
2382 : : /*
2383 : : * Mark serializable transaction as complete for predicate locking
2384 : : * purposes. This should be done as late as we can put it and still allow
2385 : : * errors to be raised for failure patterns found at commit. This is not
2386 : : * appropriate in a parallel worker however, because we aren't committing
2387 : : * the leader's transaction and its serializable state will live on.
2388 : : */
2389 [ + + ]: 613879 : if (!is_parallel_worker)
2390 : 611892 : PreCommit_CheckForSerializationFailure();
2391 : :
2392 : : /* Prevent cancel/die interrupt while cleaning up */
2393 : 613719 : HOLD_INTERRUPTS();
2394 : :
2395 : : /* Commit updates to the relation map --- do this as late as possible */
2396 : 613719 : AtEOXact_RelationMap(true, is_parallel_worker);
2397 : :
2398 : : /*
2399 : : * set the current transaction state information appropriately during
2400 : : * commit processing
2401 : : */
2402 : 613719 : s->state = TRANS_COMMIT;
2403 : 613719 : s->parallelModeLevel = 0;
2404 : 613719 : s->parallelChildXact = false; /* should be false already */
2405 : :
2406 : : /* Disable transaction timeout */
2407 [ + + ]: 613719 : if (TransactionTimeout > 0)
2408 : 1 : disable_timeout(TRANSACTION_TIMEOUT, false);
2409 : :
2410 [ + + ]: 613719 : if (!is_parallel_worker)
2411 : : {
2412 : : /*
2413 : : * We need to mark our XIDs as committed in pg_xact. This is where we
2414 : : * durably commit.
2415 : : */
2416 : 611732 : latestXid = RecordTransactionCommit();
2417 : : }
2418 : : else
2419 : : {
2420 : : /*
2421 : : * We must not mark our XID committed; the parallel leader is
2422 : : * responsible for that.
2423 : : */
2424 : 1987 : latestXid = InvalidTransactionId;
2425 : :
2426 : : /*
2427 : : * Make sure the leader will know about any WAL we wrote before it
2428 : : * commits.
2429 : : */
2430 : 1987 : ParallelWorkerReportLastRecEnd(XactLastRecEnd);
2431 : : }
2432 : :
2433 : : TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->vxid.lxid);
2434 : :
2435 : : /*
2436 : : * Let others know about no transaction in progress by me. Note that this
2437 : : * must be done _before_ releasing locks we hold and _after_
2438 : : * RecordTransactionCommit.
2439 : : */
2440 : 613719 : ProcArrayEndTransaction(MyProc, latestXid);
2441 : :
2442 : : /*
2443 : : * This is all post-commit cleanup. Note that if an error is raised here,
2444 : : * it's too late to abort the transaction. This should be just
2445 : : * noncritical resource releasing.
2446 : : *
2447 : : * The ordering of operations is not entirely random. The idea is:
2448 : : * release resources visible to other backends (eg, files, buffer pins);
2449 : : * then release locks; then release backend-local resources. We want to
2450 : : * release locks at the point where any backend waiting for us will see
2451 : : * our transaction as being fully cleaned up.
2452 : : *
2453 : : * Resources that can be associated with individual queries are handled by
2454 : : * the ResourceOwner mechanism. The other calls here are for backend-wide
2455 : : * state.
2456 : : */
2457 : :
2458 : 613719 : CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
2459 : : : XACT_EVENT_COMMIT);
2460 : :
2461 : 613719 : CurrentResourceOwner = NULL;
2462 : 613719 : ResourceOwnerRelease(TopTransactionResourceOwner,
2463 : : RESOURCE_RELEASE_BEFORE_LOCKS,
2464 : : true, true);
2465 : :
2466 : 613719 : AtEOXact_Aio(true);
2467 : :
2468 : : /* Check we've released all buffer pins */
2469 : 613719 : AtEOXact_Buffers(true);
2470 : :
2471 : : /* Clean up the relation cache */
2472 : 613719 : AtEOXact_RelationCache(true);
2473 : :
2474 : : /* Clean up the type cache */
2475 : 613719 : AtEOXact_TypeCache();
2476 : :
2477 : : /*
2478 : : * Make catalog changes visible to all backends. This has to happen after
2479 : : * relcache references are dropped (see comments for
2480 : : * AtEOXact_RelationCache), but before locks are released (if anyone is
2481 : : * waiting for lock on a relation we've modified, we want them to know
2482 : : * about the catalog change before they start using the relation).
2483 : : */
2484 : 613719 : AtEOXact_Inval(true);
2485 : :
2486 : 613719 : AtEOXact_MultiXact();
2487 : :
2488 : 613719 : ResourceOwnerRelease(TopTransactionResourceOwner,
2489 : : RESOURCE_RELEASE_LOCKS,
2490 : : true, true);
2491 : 613719 : ResourceOwnerRelease(TopTransactionResourceOwner,
2492 : : RESOURCE_RELEASE_AFTER_LOCKS,
2493 : : true, true);
2494 : :
2495 : : /*
2496 : : * Likewise, dropping of files deleted during the transaction is best done
2497 : : * after releasing relcache and buffer pins. (This is not strictly
2498 : : * necessary during commit, since such pins should have been released
2499 : : * already, but this ordering is definitely critical during abort.) Since
2500 : : * this may take many seconds, also delay until after releasing locks.
2501 : : * Other backends will observe the attendant catalog changes and not
2502 : : * attempt to access affected files.
2503 : : */
2504 : 613719 : smgrDoPendingDeletes(true);
2505 : :
2506 : : /*
2507 : : * Send out notification signals to other backends (and do other
2508 : : * post-commit NOTIFY cleanup). This must not happen until after our
2509 : : * transaction is fully done from the viewpoint of other backends.
2510 : : */
2511 : 613719 : AtCommit_Notify();
2512 : :
2513 : : /*
2514 : : * Everything after this should be purely internal-to-this-backend
2515 : : * cleanup.
2516 : : */
2517 : 613719 : AtEOXact_GUC(true, 1);
2518 : 613719 : AtEOXact_SPI(true);
2519 : 613719 : AtEOXact_Enum();
2520 : 613719 : AtEOXact_on_commit_actions(true);
2521 : 613719 : AtEOXact_Namespace(true, is_parallel_worker);
2522 : 613719 : AtEOXact_SMgr();
2523 : 613719 : AtEOXact_Files(true);
2524 : 613719 : AtEOXact_ComboCid();
2525 : 613719 : AtEOXact_HashTables(true);
2526 : 613719 : AtEOXact_RI(true);
2527 : 613719 : AtEOXact_PgStat(true, is_parallel_worker);
2528 : 613719 : AtEOXact_Snapshot(true, false);
2529 : 613719 : AtEOXact_ApplyLauncher(true);
2530 : 613719 : AtEOXact_LogicalRepWorkers(true);
2531 : 613719 : AtEOXact_LogicalCtl();
2532 : 613719 : pgstat_report_xact_timestamp(0);
2533 : :
2534 : 613719 : ResourceOwnerDelete(TopTransactionResourceOwner);
2535 : 613719 : s->curTransactionOwner = NULL;
2536 : 613719 : CurTransactionResourceOwner = NULL;
2537 : 613719 : TopTransactionResourceOwner = NULL;
2538 : :
2539 : 613719 : AtCommit_Memory();
2540 : :
2541 : 613719 : s->fullTransactionId = InvalidFullTransactionId;
2542 : 613719 : s->subTransactionId = InvalidSubTransactionId;
2543 : 613719 : s->nestingLevel = 0;
2544 : 613719 : s->gucNestLevel = 0;
2545 : 613719 : s->childXids = NULL;
2546 : 613719 : s->nChildXids = 0;
2547 : 613719 : s->maxChildXids = 0;
2548 : :
2549 : 613719 : XactTopFullTransactionId = InvalidFullTransactionId;
2550 : 613719 : nParallelCurrentXids = 0;
2551 : :
2552 : : /*
2553 : : * done with commit processing, set current transaction state back to
2554 : : * default
2555 : : */
2556 : 613719 : s->state = TRANS_DEFAULT;
2557 : :
2558 : 613719 : RESUME_INTERRUPTS();
2559 : 613719 : }
2560 : :
2561 : :
2562 : : /*
2563 : : * PrepareTransaction
2564 : : *
2565 : : * NB: if you change this routine, better look at CommitTransaction too!
2566 : : */
2567 : : static void
2568 : 395 : PrepareTransaction(void)
2569 : : {
2570 : 395 : TransactionState s = CurrentTransactionState;
2571 : 395 : FullTransactionId fxid = GetCurrentFullTransactionId();
2572 : : GlobalTransaction gxact;
2573 : : TimestampTz prepared_at;
2574 : :
2575 : : Assert(!IsInParallelMode());
2576 : :
2577 : 395 : ShowTransactionState("PrepareTransaction");
2578 : :
2579 : : /*
2580 : : * check the current transaction state
2581 : : */
2582 [ - + ]: 395 : if (s->state != TRANS_INPROGRESS)
2583 [ # # ]: 0 : elog(WARNING, "PrepareTransaction while in %s state",
2584 : : TransStateAsString(s->state));
2585 : : Assert(s->parent == NULL);
2586 : :
2587 : : /*
2588 : : * Do pre-commit processing that involves calling user-defined code, such
2589 : : * as triggers. Since closing cursors could queue trigger actions,
2590 : : * triggers could open cursors, etc, we have to keep looping until there's
2591 : : * nothing left to do.
2592 : : */
2593 : : for (;;)
2594 : : {
2595 : : /*
2596 : : * Fire all currently pending deferred triggers.
2597 : : */
2598 : 397 : AfterTriggerFireDeferred();
2599 : :
2600 : : /*
2601 : : * Close open portals (converting holdable ones into static portals).
2602 : : * If there weren't any, we are done ... otherwise loop back to check
2603 : : * if they queued deferred triggers. Lather, rinse, repeat.
2604 : : */
2605 [ + + ]: 397 : if (!PreCommit_Portals(true))
2606 : 395 : break;
2607 : : }
2608 : :
2609 : 395 : CallXactCallbacks(XACT_EVENT_PRE_PREPARE);
2610 : :
2611 : : /*
2612 : : * The remaining actions cannot call any user-defined code, so it's safe
2613 : : * to start shutting down within-transaction services. But note that most
2614 : : * of this stuff could still throw an error, which would switch us into
2615 : : * the transaction-abort path.
2616 : : */
2617 : :
2618 : : /* Shut down the deferred-trigger manager */
2619 : 394 : AfterTriggerEndXact(true);
2620 : :
2621 : : /*
2622 : : * Let ON COMMIT management do its thing (must happen after closing
2623 : : * cursors, to avoid dangling-reference problems)
2624 : : */
2625 : 394 : PreCommit_on_commit_actions();
2626 : :
2627 : : /*
2628 : : * Synchronize files that are created and not WAL-logged during this
2629 : : * transaction. This must happen before EndPrepare(), so that we don't see
2630 : : * committed-but-broken files after a crash and COMMIT PREPARED.
2631 : : */
2632 : 394 : smgrDoPendingSyncs(true, false);
2633 : :
2634 : : /* close large objects before lower-level cleanup */
2635 : 394 : AtEOXact_LargeObject(true);
2636 : :
2637 : : /* NOTIFY requires no work at this point */
2638 : :
2639 : : /*
2640 : : * Mark serializable transaction as complete for predicate locking
2641 : : * purposes. This should be done as late as we can put it and still allow
2642 : : * errors to be raised for failure patterns found at commit.
2643 : : */
2644 : 394 : PreCommit_CheckForSerializationFailure();
2645 : :
2646 : : /*
2647 : : * Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
2648 : : * this transaction. Having the prepared xact hold locks on another
2649 : : * backend's temp table seems a bad idea --- for instance it would prevent
2650 : : * the backend from exiting. There are other problems too, such as how to
2651 : : * clean up the source backend's local buffers and ON COMMIT state if the
2652 : : * prepared xact includes a DROP of a temp table.
2653 : : *
2654 : : * Other objects types, like functions, operators or extensions, share the
2655 : : * same restriction as they should not be created, locked or dropped as
2656 : : * this can mess up with this session or even a follow-up session trying
2657 : : * to use the same temporary namespace.
2658 : : *
2659 : : * We must check this after executing any ON COMMIT actions, because they
2660 : : * might still access a temp relation.
2661 : : *
2662 : : * XXX In principle this could be relaxed to allow some useful special
2663 : : * cases, such as a temp table created and dropped all within the
2664 : : * transaction. That seems to require much more bookkeeping though.
2665 : : */
2666 [ + + ]: 394 : if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPNAMESPACE))
2667 [ + - ]: 45 : ereport(ERROR,
2668 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2669 : : errmsg("cannot PREPARE a transaction that has operated on temporary objects")));
2670 : :
2671 : : /*
2672 : : * Likewise, don't allow PREPARE after pg_export_snapshot. This could be
2673 : : * supported if we added cleanup logic to twophase.c, but for now it
2674 : : * doesn't seem worth the trouble.
2675 : : */
2676 [ - + ]: 349 : if (XactHasExportedSnapshots())
2677 [ # # ]: 0 : ereport(ERROR,
2678 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2679 : : errmsg("cannot PREPARE a transaction that has exported snapshots")));
2680 : :
2681 : : /* Prevent cancel/die interrupt while cleaning up */
2682 : 349 : HOLD_INTERRUPTS();
2683 : :
2684 : : /*
2685 : : * set the current transaction state information appropriately during
2686 : : * prepare processing
2687 : : */
2688 : 349 : s->state = TRANS_PREPARE;
2689 : :
2690 : : /* Disable transaction timeout */
2691 [ - + ]: 349 : if (TransactionTimeout > 0)
2692 : 0 : disable_timeout(TRANSACTION_TIMEOUT, false);
2693 : :
2694 : 349 : prepared_at = GetCurrentTimestamp();
2695 : :
2696 : : /*
2697 : : * Reserve the GID for this transaction. This could fail if the requested
2698 : : * GID is invalid or already in use.
2699 : : */
2700 : 349 : gxact = MarkAsPreparing(fxid, prepareGID, prepared_at,
2701 : : GetUserId(), MyDatabaseId);
2702 : 331 : prepareGID = NULL;
2703 : :
2704 : : /*
2705 : : * Collect data for the 2PC state file. Note that in general, no actual
2706 : : * state change should happen in the called modules during this step,
2707 : : * since it's still possible to fail before commit, and in that case we
2708 : : * want transaction abort to be able to clean up. (In particular, the
2709 : : * AtPrepare routines may error out if they find cases they cannot
2710 : : * handle.) State cleanup should happen in the PostPrepare routines
2711 : : * below. However, some modules can go ahead and clear state here because
2712 : : * they wouldn't do anything with it during abort anyway.
2713 : : *
2714 : : * Note: because the 2PC state file records will be replayed in the same
2715 : : * order they are made, the order of these calls has to match the order in
2716 : : * which we want things to happen during COMMIT PREPARED or ROLLBACK
2717 : : * PREPARED; in particular, pay attention to whether things should happen
2718 : : * before or after releasing the transaction's locks.
2719 : : */
2720 : 331 : StartPrepare(gxact);
2721 : :
2722 : 331 : AtPrepare_Notify();
2723 : 331 : AtPrepare_Locks();
2724 : 329 : AtPrepare_PredicateLocks();
2725 : 329 : AtPrepare_PgStat();
2726 : 329 : AtPrepare_MultiXact();
2727 : 329 : AtPrepare_RelationMap();
2728 : :
2729 : : /*
2730 : : * Here is where we really truly prepare.
2731 : : *
2732 : : * We have to record transaction prepares even if we didn't make any
2733 : : * updates, because the transaction manager might get confused if we lose
2734 : : * a global transaction.
2735 : : */
2736 : 329 : EndPrepare(gxact);
2737 : :
2738 : : /*
2739 : : * Now we clean up backend-internal state and release internal resources.
2740 : : */
2741 : :
2742 : : /* Reset XactLastRecEnd until the next transaction writes something */
2743 : 329 : XactLastRecEnd = 0;
2744 : :
2745 : : /*
2746 : : * Transfer our locks to a dummy PGPROC. This has to be done before
2747 : : * ProcArrayClearTransaction(). Otherwise, a GetLockConflicts() would
2748 : : * conclude "xact already committed or aborted" for our locks.
2749 : : */
2750 : 329 : PostPrepare_Locks(fxid);
2751 : :
2752 : : /*
2753 : : * Let others know about no transaction in progress by me. This has to be
2754 : : * done *after* the prepared transaction has been marked valid, else
2755 : : * someone may think it is unlocked and recyclable.
2756 : : */
2757 : 329 : ProcArrayClearTransaction(MyProc);
2758 : :
2759 : : /*
2760 : : * In normal commit-processing, this is all non-critical post-transaction
2761 : : * cleanup. When the transaction is prepared, however, it's important
2762 : : * that the locks and other per-backend resources are transferred to the
2763 : : * prepared transaction's PGPROC entry. Note that if an error is raised
2764 : : * here, it's too late to abort the transaction. XXX: This probably should
2765 : : * be in a critical section, to force a PANIC if any of this fails, but
2766 : : * that cure could be worse than the disease.
2767 : : */
2768 : :
2769 : 329 : CallXactCallbacks(XACT_EVENT_PREPARE);
2770 : :
2771 : 329 : ResourceOwnerRelease(TopTransactionResourceOwner,
2772 : : RESOURCE_RELEASE_BEFORE_LOCKS,
2773 : : true, true);
2774 : :
2775 : 329 : AtEOXact_Aio(true);
2776 : :
2777 : : /* Check we've released all buffer pins */
2778 : 329 : AtEOXact_Buffers(true);
2779 : :
2780 : : /* Clean up the relation cache */
2781 : 329 : AtEOXact_RelationCache(true);
2782 : :
2783 : : /* Clean up the type cache */
2784 : 329 : AtEOXact_TypeCache();
2785 : :
2786 : : /* notify doesn't need a postprepare call */
2787 : :
2788 : 329 : PostPrepare_PgStat();
2789 : :
2790 : 329 : PostPrepare_Inval();
2791 : :
2792 : 329 : PostPrepare_smgr();
2793 : :
2794 : 329 : PostPrepare_MultiXact(fxid);
2795 : :
2796 : 329 : PostPrepare_PredicateLocks(fxid);
2797 : :
2798 : 329 : ResourceOwnerRelease(TopTransactionResourceOwner,
2799 : : RESOURCE_RELEASE_LOCKS,
2800 : : true, true);
2801 : 329 : ResourceOwnerRelease(TopTransactionResourceOwner,
2802 : : RESOURCE_RELEASE_AFTER_LOCKS,
2803 : : true, true);
2804 : :
2805 : : /*
2806 : : * Allow another backend to finish the transaction. After
2807 : : * PostPrepare_Twophase(), the transaction is completely detached from our
2808 : : * backend. The rest is just non-critical cleanup of backend-local state.
2809 : : */
2810 : 329 : PostPrepare_Twophase();
2811 : :
2812 : : /* PREPARE acts the same as COMMIT as far as GUC is concerned */
2813 : 329 : AtEOXact_GUC(true, 1);
2814 : 329 : AtEOXact_SPI(true);
2815 : 329 : AtEOXact_Enum();
2816 : 329 : AtEOXact_on_commit_actions(true);
2817 : 329 : AtEOXact_Namespace(true, false);
2818 : 329 : AtEOXact_SMgr();
2819 : 329 : AtEOXact_Files(true);
2820 : 329 : AtEOXact_ComboCid();
2821 : 329 : AtEOXact_HashTables(true);
2822 : 329 : AtEOXact_RI(true);
2823 : : /* don't call AtEOXact_PgStat here; we fixed pgstat state above */
2824 : 329 : AtEOXact_Snapshot(true, true);
2825 : : /* we treat PREPARE as ROLLBACK so far as waking workers goes */
2826 : 329 : AtEOXact_ApplyLauncher(false);
2827 : 329 : AtEOXact_LogicalRepWorkers(false);
2828 : 329 : AtEOXact_LogicalCtl();
2829 : 329 : pgstat_report_xact_timestamp(0);
2830 : :
2831 : 329 : CurrentResourceOwner = NULL;
2832 : 329 : ResourceOwnerDelete(TopTransactionResourceOwner);
2833 : 329 : s->curTransactionOwner = NULL;
2834 : 329 : CurTransactionResourceOwner = NULL;
2835 : 329 : TopTransactionResourceOwner = NULL;
2836 : :
2837 : 329 : AtCommit_Memory();
2838 : :
2839 : 329 : s->fullTransactionId = InvalidFullTransactionId;
2840 : 329 : s->subTransactionId = InvalidSubTransactionId;
2841 : 329 : s->nestingLevel = 0;
2842 : 329 : s->gucNestLevel = 0;
2843 : 329 : s->childXids = NULL;
2844 : 329 : s->nChildXids = 0;
2845 : 329 : s->maxChildXids = 0;
2846 : :
2847 : 329 : XactTopFullTransactionId = InvalidFullTransactionId;
2848 : 329 : nParallelCurrentXids = 0;
2849 : :
2850 : : /*
2851 : : * done with 1st phase commit processing, set current transaction state
2852 : : * back to default
2853 : : */
2854 : 329 : s->state = TRANS_DEFAULT;
2855 : :
2856 : 329 : RESUME_INTERRUPTS();
2857 : 329 : }
2858 : :
2859 : :
2860 : : /*
2861 : : * AbortTransaction
2862 : : */
2863 : : static void
2864 : 35930 : AbortTransaction(void)
2865 : : {
2866 : 35930 : TransactionState s = CurrentTransactionState;
2867 : : TransactionId latestXid;
2868 : : bool is_parallel_worker;
2869 : :
2870 : : /* Prevent cancel/die interrupt while cleaning up */
2871 : 35930 : HOLD_INTERRUPTS();
2872 : :
2873 : : /* Disable transaction timeout */
2874 [ + + ]: 35930 : if (TransactionTimeout > 0)
2875 : 1 : disable_timeout(TRANSACTION_TIMEOUT, false);
2876 : :
2877 : : /* Make sure we have a valid memory context and resource owner */
2878 : 35930 : AtAbort_Memory();
2879 : 35930 : AtAbort_ResourceOwner();
2880 : :
2881 : : /*
2882 : : * Release any LW locks we might be holding as quickly as possible.
2883 : : * (Regular locks, however, must be held till we finish aborting.)
2884 : : * Releasing LW locks is critical since we might try to grab them again
2885 : : * while cleaning up!
2886 : : */
2887 : 35930 : LWLockReleaseAll();
2888 : :
2889 : : /*
2890 : : * Cleanup waiting for LSN if any.
2891 : : */
2892 : 35930 : WaitLSNCleanup();
2893 : :
2894 : : /* Clear wait information and command progress indicator */
2895 : 35930 : pgstat_report_wait_end();
2896 : 35930 : pgstat_progress_end_command();
2897 : :
2898 : 35930 : pgaio_error_cleanup();
2899 : :
2900 : : /* Clean up buffer content locks, too */
2901 : 35930 : UnlockBuffers();
2902 : :
2903 : : /* Reset WAL record construction state */
2904 : 35930 : XLogResetInsertion();
2905 : :
2906 : : /* Cancel condition variable sleep */
2907 : 35930 : ConditionVariableCancelSleep();
2908 : :
2909 : : /*
2910 : : * Also clean up any open wait for lock, since the lock manager will choke
2911 : : * if we try to wait for another lock before doing this.
2912 : : */
2913 : 35930 : LockErrorCleanup();
2914 : :
2915 : : /*
2916 : : * If any timeout events are still active, make sure the timeout interrupt
2917 : : * is scheduled. This covers possible loss of a timeout interrupt due to
2918 : : * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
2919 : : * We delay this till after LockErrorCleanup so that we don't uselessly
2920 : : * reschedule lock or deadlock check timeouts.
2921 : : */
2922 : 35930 : reschedule_timeouts();
2923 : :
2924 : : /*
2925 : : * Re-enable signals, in case we got here by longjmp'ing out of a signal
2926 : : * handler. We do this fairly early in the sequence so that the timeout
2927 : : * infrastructure will be functional if needed while aborting.
2928 : : */
2929 : 35930 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
2930 : :
2931 : : /*
2932 : : * check the current transaction state
2933 : : */
2934 : 35930 : is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
2935 [ + + - + ]: 35930 : if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
2936 [ # # ]: 0 : elog(WARNING, "AbortTransaction while in %s state",
2937 : : TransStateAsString(s->state));
2938 : : Assert(s->parent == NULL);
2939 : :
2940 : : /*
2941 : : * set the current transaction state information appropriately during the
2942 : : * abort processing
2943 : : */
2944 : 35930 : s->state = TRANS_ABORT;
2945 : :
2946 : : /*
2947 : : * Reset user ID which might have been changed transiently. We need this
2948 : : * to clean up in case control escaped out of a SECURITY DEFINER function
2949 : : * or other local change of CurrentUserId; therefore, the prior value of
2950 : : * SecurityRestrictionContext also needs to be restored.
2951 : : *
2952 : : * (Note: it is not necessary to restore session authorization or role
2953 : : * settings here because those can only be changed via GUC, and GUC will
2954 : : * take care of rolling them back if need be.)
2955 : : */
2956 : 35930 : SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
2957 : :
2958 : : /* Forget about any active REINDEX. */
2959 : 35930 : ResetReindexState(s->nestingLevel);
2960 : :
2961 : : /* Reset logical streaming state. */
2962 : 35930 : ResetLogicalStreamingState();
2963 : :
2964 : : /* Reset snapshot export state. */
2965 : 35930 : SnapBuildResetExportedSnapshotState();
2966 : :
2967 : : /*
2968 : : * If this xact has started any unfinished parallel operation, clean up
2969 : : * its workers and exit parallel mode. Don't warn about leaked resources.
2970 : : */
2971 : 35930 : AtEOXact_Parallel(false);
2972 : 35930 : s->parallelModeLevel = 0;
2973 : 35930 : s->parallelChildXact = false; /* should be false already */
2974 : :
2975 : : /*
2976 : : * do abort processing
2977 : : */
2978 : 35930 : AfterTriggerEndXact(false); /* 'false' means it's abort */
2979 : 35930 : AtAbort_Portals();
2980 : 35930 : smgrDoPendingSyncs(false, is_parallel_worker);
2981 : 35930 : AtEOXact_LargeObject(false);
2982 : 35930 : AtAbort_Notify();
2983 : 35930 : AtEOXact_RelationMap(false, is_parallel_worker);
2984 : 35930 : AtAbort_Twophase();
2985 : :
2986 : : /*
2987 : : * Advertise the fact that we aborted in pg_xact (assuming that we got as
2988 : : * far as assigning an XID to advertise). But if we're inside a parallel
2989 : : * worker, skip this; the user backend must be the one to write the abort
2990 : : * record.
2991 : : */
2992 [ + + ]: 35930 : if (!is_parallel_worker)
2993 : 35922 : latestXid = RecordTransactionAbort(false);
2994 : : else
2995 : : {
2996 : 8 : latestXid = InvalidTransactionId;
2997 : :
2998 : : /*
2999 : : * Since the parallel leader won't get our value of XactLastRecEnd in
3000 : : * this case, we nudge WAL-writer ourselves in this case. See related
3001 : : * comments in RecordTransactionAbort for why this matters.
3002 : : */
3003 : 8 : XLogSetAsyncXactLSN(XactLastRecEnd);
3004 : : }
3005 : :
3006 : : TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->vxid.lxid);
3007 : :
3008 : : /*
3009 : : * Let others know about no transaction in progress by me. Note that this
3010 : : * must be done _before_ releasing locks we hold and _after_
3011 : : * RecordTransactionAbort.
3012 : : */
3013 : 35930 : ProcArrayEndTransaction(MyProc, latestXid);
3014 : :
3015 : : /*
3016 : : * Post-abort cleanup. See notes in CommitTransaction() concerning
3017 : : * ordering. We can skip all of it if the transaction failed before
3018 : : * creating a resource owner.
3019 : : */
3020 [ + - ]: 35930 : if (TopTransactionResourceOwner != NULL)
3021 : : {
3022 [ + + ]: 35930 : if (is_parallel_worker)
3023 : 8 : CallXactCallbacks(XACT_EVENT_PARALLEL_ABORT);
3024 : : else
3025 : 35922 : CallXactCallbacks(XACT_EVENT_ABORT);
3026 : :
3027 : 35930 : ResourceOwnerRelease(TopTransactionResourceOwner,
3028 : : RESOURCE_RELEASE_BEFORE_LOCKS,
3029 : : false, true);
3030 : 35930 : AtEOXact_Aio(false);
3031 : 35930 : AtEOXact_Buffers(false);
3032 : 35930 : AtEOXact_RelationCache(false);
3033 : 35930 : AtEOXact_TypeCache();
3034 : 35930 : AtEOXact_Inval(false);
3035 : 35930 : AtEOXact_MultiXact();
3036 : 35930 : ResourceOwnerRelease(TopTransactionResourceOwner,
3037 : : RESOURCE_RELEASE_LOCKS,
3038 : : false, true);
3039 : 35930 : ResourceOwnerRelease(TopTransactionResourceOwner,
3040 : : RESOURCE_RELEASE_AFTER_LOCKS,
3041 : : false, true);
3042 : 35930 : smgrDoPendingDeletes(false);
3043 : :
3044 : 35930 : AtEOXact_GUC(false, 1);
3045 : 35930 : AtEOXact_SPI(false);
3046 : 35930 : AtEOXact_Enum();
3047 : 35930 : AtEOXact_on_commit_actions(false);
3048 : 35930 : AtEOXact_Namespace(false, is_parallel_worker);
3049 : 35930 : AtEOXact_SMgr();
3050 : 35930 : AtEOXact_Files(false);
3051 : 35930 : AtEOXact_ComboCid();
3052 : 35930 : AtEOXact_HashTables(false);
3053 : 35930 : AtEOXact_RI(false);
3054 : 35930 : AtEOXact_PgStat(false, is_parallel_worker);
3055 : 35930 : AtEOXact_ApplyLauncher(false);
3056 : 35930 : AtEOXact_LogicalRepWorkers(false);
3057 : 35930 : pgstat_report_xact_timestamp(0);
3058 : : }
3059 : :
3060 : : /*
3061 : : * State remains TRANS_ABORT until CleanupTransaction().
3062 : : */
3063 : 35930 : RESUME_INTERRUPTS();
3064 : 35930 : }
3065 : :
3066 : : /*
3067 : : * CleanupTransaction
3068 : : */
3069 : : static void
3070 : 35930 : CleanupTransaction(void)
3071 : : {
3072 : 35930 : TransactionState s = CurrentTransactionState;
3073 : :
3074 : : /*
3075 : : * State should still be TRANS_ABORT from AbortTransaction().
3076 : : */
3077 [ - + ]: 35930 : if (s->state != TRANS_ABORT)
3078 [ # # ]: 0 : elog(FATAL, "CleanupTransaction: unexpected state %s",
3079 : : TransStateAsString(s->state));
3080 : :
3081 : : /*
3082 : : * do abort cleanup processing
3083 : : */
3084 : 35930 : AtCleanup_Portals(); /* now safe to release portal memory */
3085 : 35930 : AtEOXact_Snapshot(false, true); /* and release the transaction's snapshots */
3086 : :
3087 : 35930 : CurrentResourceOwner = NULL; /* and resource owner */
3088 [ + - ]: 35930 : if (TopTransactionResourceOwner)
3089 : 35930 : ResourceOwnerDelete(TopTransactionResourceOwner);
3090 : 35930 : s->curTransactionOwner = NULL;
3091 : 35930 : CurTransactionResourceOwner = NULL;
3092 : 35930 : TopTransactionResourceOwner = NULL;
3093 : :
3094 : 35930 : AtCleanup_Memory(); /* and transaction memory */
3095 : :
3096 : 35930 : s->fullTransactionId = InvalidFullTransactionId;
3097 : 35930 : s->subTransactionId = InvalidSubTransactionId;
3098 : 35930 : s->nestingLevel = 0;
3099 : 35930 : s->gucNestLevel = 0;
3100 : 35930 : s->childXids = NULL;
3101 : 35930 : s->nChildXids = 0;
3102 : 35930 : s->maxChildXids = 0;
3103 : 35930 : s->parallelModeLevel = 0;
3104 : 35930 : s->parallelChildXact = false;
3105 : :
3106 : 35930 : XactTopFullTransactionId = InvalidFullTransactionId;
3107 : 35930 : nParallelCurrentXids = 0;
3108 : :
3109 : : /*
3110 : : * Apply any pending XLogLogicalInfo update. This must be done here
3111 : : * rather than in AbortTransaction(), because a failed transaction block
3112 : : * keeps its XID until ROLLBACK, so a barrier absorbed meanwhile is
3113 : : * deferred. Unlike CommitTransaction() and PrepareTransaction(), we are
3114 : : * not necessarily holding interrupts here, so do this after resetting the
3115 : : * top-level XID; otherwise a barrier absorbed in between would be left
3116 : : * pending into the next transaction.
3117 : : */
3118 : 35930 : AtEOXact_LogicalCtl();
3119 : :
3120 : : /*
3121 : : * done with abort processing, set current transaction state back to
3122 : : * default
3123 : : */
3124 : 35930 : s->state = TRANS_DEFAULT;
3125 : 35930 : }
3126 : :
3127 : : /*
3128 : : * StartTransactionCommand
3129 : : */
3130 : : void
3131 : 762940 : StartTransactionCommand(void)
3132 : : {
3133 : 762940 : TransactionState s = CurrentTransactionState;
3134 : :
3135 [ + + + - : 762940 : switch (s->blockState)
- ]
3136 : : {
3137 : : /*
3138 : : * if we aren't in a transaction block, we just do our usual start
3139 : : * transaction.
3140 : : */
3141 : 647943 : case TBLOCK_DEFAULT:
3142 : 647943 : StartTransaction();
3143 : 647943 : s->blockState = TBLOCK_STARTED;
3144 : 647943 : break;
3145 : :
3146 : : /*
3147 : : * We are somewhere in a transaction block or subtransaction and
3148 : : * about to start a new command. For now we do nothing, but
3149 : : * someday we may do command-local resource initialization. (Note
3150 : : * that any needed CommandCounterIncrement was done by the
3151 : : * previous CommitTransactionCommand.)
3152 : : */
3153 : 113811 : case TBLOCK_INPROGRESS:
3154 : : case TBLOCK_IMPLICIT_INPROGRESS:
3155 : : case TBLOCK_SUBINPROGRESS:
3156 : 113811 : break;
3157 : :
3158 : : /*
3159 : : * Here we are in a failed transaction block (one of the commands
3160 : : * caused an abort) so we do nothing but remain in the abort
3161 : : * state. Eventually we will get a ROLLBACK command which will
3162 : : * get us out of this state. (It is up to other code to ensure
3163 : : * that no commands other than ROLLBACK will be processed in these
3164 : : * states.)
3165 : : */
3166 : 1186 : case TBLOCK_ABORT:
3167 : : case TBLOCK_SUBABORT:
3168 : 1186 : break;
3169 : :
3170 : : /* These cases are invalid. */
3171 : 0 : case TBLOCK_STARTED:
3172 : : case TBLOCK_BEGIN:
3173 : : case TBLOCK_PARALLEL_INPROGRESS:
3174 : : case TBLOCK_SUBBEGIN:
3175 : : case TBLOCK_END:
3176 : : case TBLOCK_SUBRELEASE:
3177 : : case TBLOCK_SUBCOMMIT:
3178 : : case TBLOCK_ABORT_END:
3179 : : case TBLOCK_SUBABORT_END:
3180 : : case TBLOCK_ABORT_PENDING:
3181 : : case TBLOCK_SUBABORT_PENDING:
3182 : : case TBLOCK_SUBRESTART:
3183 : : case TBLOCK_SUBABORT_RESTART:
3184 : : case TBLOCK_PREPARE:
3185 [ # # ]: 0 : elog(ERROR, "StartTransactionCommand: unexpected state %s",
3186 : : BlockStateAsString(s->blockState));
3187 : : break;
3188 : : }
3189 : :
3190 : : /*
3191 : : * We must switch to CurTransactionContext before returning. This is
3192 : : * already done if we called StartTransaction, otherwise not.
3193 : : */
3194 : : Assert(CurTransactionContext != NULL);
3195 : 762940 : MemoryContextSwitchTo(CurTransactionContext);
3196 : 762940 : }
3197 : :
3198 : :
3199 : : /*
3200 : : * Simple system for saving and restoring transaction characteristics
3201 : : * (isolation level, read only, deferrable). We need this for transaction
3202 : : * chaining, so that we can set the characteristics of the new transaction to
3203 : : * be the same as the previous one. (We need something like this because the
3204 : : * GUC system resets the characteristics at transaction end, so for example
3205 : : * just skipping the reset in StartTransaction() won't work.)
3206 : : */
3207 : : void
3208 : 729661 : SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)
3209 : : {
3210 : 729661 : s->save_XactIsoLevel = XactIsoLevel;
3211 : 729661 : s->save_XactReadOnly = XactReadOnly;
3212 : 729661 : s->save_XactDeferrable = XactDeferrable;
3213 : 729661 : }
3214 : :
3215 : : void
3216 : 44 : RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
3217 : : {
3218 : 44 : XactIsoLevel = s->save_XactIsoLevel;
3219 : 44 : XactReadOnly = s->save_XactReadOnly;
3220 : 44 : XactDeferrable = s->save_XactDeferrable;
3221 : 44 : }
3222 : :
3223 : : /*
3224 : : * CommitTransactionCommand -- a wrapper function handling the
3225 : : * loop over subtransactions to avoid a potentially dangerous recursion
3226 : : * in CommitTransactionCommandInternal().
3227 : : */
3228 : : void
3229 : 729342 : CommitTransactionCommand(void)
3230 : : {
3231 : : /*
3232 : : * Repeatedly call CommitTransactionCommandInternal() until all the work
3233 : : * is done.
3234 : : */
3235 [ + + ]: 729657 : while (!CommitTransactionCommandInternal())
3236 : : {
3237 : : }
3238 : 728962 : }
3239 : :
3240 : : /*
3241 : : * CommitTransactionCommandInternal - a function doing an iteration of work
3242 : : * regarding handling the commit transaction command. In the case of
3243 : : * subtransactions more than one iterations could be required. Returns
3244 : : * true when no more iterations required, false otherwise.
3245 : : */
3246 : : static bool
3247 : 729657 : CommitTransactionCommandInternal(void)
3248 : : {
3249 : 729657 : TransactionState s = CurrentTransactionState;
3250 : : SavedTransactionCharacteristics savetc;
3251 : :
3252 : : /* Must save in case we need to restore below */
3253 : 729657 : SaveTransactionCharacteristics(&savetc);
3254 : :
3255 [ - + + + : 729657 : switch (s->blockState)
+ + + + +
+ + + + +
+ + - ]
3256 : : {
3257 : : /*
3258 : : * These shouldn't happen. TBLOCK_DEFAULT means the previous
3259 : : * StartTransactionCommand didn't set the STARTED state
3260 : : * appropriately, while TBLOCK_PARALLEL_INPROGRESS should be ended
3261 : : * by EndParallelWorkerTransaction(), not this function.
3262 : : */
3263 : 0 : case TBLOCK_DEFAULT:
3264 : : case TBLOCK_PARALLEL_INPROGRESS:
3265 [ # # ]: 0 : elog(FATAL, "CommitTransactionCommand: unexpected state %s",
3266 : : BlockStateAsString(s->blockState));
3267 : : break;
3268 : :
3269 : : /*
3270 : : * If we aren't in a transaction block, just do our usual
3271 : : * transaction commit, and return to the idle state.
3272 : : */
3273 : 602859 : case TBLOCK_STARTED:
3274 : 602859 : CommitTransaction();
3275 : 602816 : s->blockState = TBLOCK_DEFAULT;
3276 : 602816 : break;
3277 : :
3278 : : /*
3279 : : * We are completing a "BEGIN TRANSACTION" command, so we change
3280 : : * to the "transaction block in progress" state and return. (We
3281 : : * assume the BEGIN did nothing to the database, so we need no
3282 : : * CommandCounterIncrement.)
3283 : : */
3284 : 12568 : case TBLOCK_BEGIN:
3285 : 12568 : s->blockState = TBLOCK_INPROGRESS;
3286 : 12568 : break;
3287 : :
3288 : : /*
3289 : : * This is the case when we have finished executing a command
3290 : : * someplace within a transaction block. We increment the command
3291 : : * counter and return.
3292 : : */
3293 : 78547 : case TBLOCK_INPROGRESS:
3294 : : case TBLOCK_IMPLICIT_INPROGRESS:
3295 : : case TBLOCK_SUBINPROGRESS:
3296 : 78547 : CommandCounterIncrement();
3297 : 78547 : break;
3298 : :
3299 : : /*
3300 : : * We are completing a "COMMIT" command. Do it and return to the
3301 : : * idle state.
3302 : : */
3303 : 8810 : case TBLOCK_END:
3304 : 8810 : CommitTransaction();
3305 : 8556 : s->blockState = TBLOCK_DEFAULT;
3306 [ + + ]: 8556 : if (s->chain)
3307 : : {
3308 : 8 : StartTransaction();
3309 : 8 : s->blockState = TBLOCK_INPROGRESS;
3310 : 8 : s->chain = false;
3311 : 8 : RestoreTransactionCharacteristics(&savetc);
3312 : : }
3313 : 8556 : break;
3314 : :
3315 : : /*
3316 : : * Here we are in the middle of a transaction block but one of the
3317 : : * commands caused an abort so we do nothing but remain in the
3318 : : * abort state. Eventually we will get a ROLLBACK command.
3319 : : */
3320 : 13 : case TBLOCK_ABORT:
3321 : : case TBLOCK_SUBABORT:
3322 : 13 : break;
3323 : :
3324 : : /*
3325 : : * Here we were in an aborted transaction block and we just got
3326 : : * the ROLLBACK command from the user, so clean up the
3327 : : * already-aborted transaction and return to the idle state.
3328 : : */
3329 : 891 : case TBLOCK_ABORT_END:
3330 : 891 : CleanupTransaction();
3331 : 891 : s->blockState = TBLOCK_DEFAULT;
3332 [ + + ]: 891 : if (s->chain)
3333 : : {
3334 : 8 : StartTransaction();
3335 : 8 : s->blockState = TBLOCK_INPROGRESS;
3336 : 8 : s->chain = false;
3337 : 8 : RestoreTransactionCharacteristics(&savetc);
3338 : : }
3339 : 891 : break;
3340 : :
3341 : : /*
3342 : : * Here we were in a perfectly good transaction block but the user
3343 : : * told us to ROLLBACK anyway. We have to abort the transaction
3344 : : * and then clean up.
3345 : : */
3346 : 1844 : case TBLOCK_ABORT_PENDING:
3347 : 1844 : AbortTransaction();
3348 : 1844 : CleanupTransaction();
3349 : 1844 : s->blockState = TBLOCK_DEFAULT;
3350 [ + + ]: 1844 : if (s->chain)
3351 : : {
3352 : 12 : StartTransaction();
3353 : 12 : s->blockState = TBLOCK_INPROGRESS;
3354 : 12 : s->chain = false;
3355 : 12 : RestoreTransactionCharacteristics(&savetc);
3356 : : }
3357 : 1844 : break;
3358 : :
3359 : : /*
3360 : : * We are completing a "PREPARE TRANSACTION" command. Do it and
3361 : : * return to the idle state.
3362 : : */
3363 : 270 : case TBLOCK_PREPARE:
3364 : 270 : PrepareTransaction();
3365 : 206 : s->blockState = TBLOCK_DEFAULT;
3366 : 206 : break;
3367 : :
3368 : : /*
3369 : : * The user issued a SAVEPOINT inside a transaction block. Start a
3370 : : * subtransaction. (DefineSavepoint already did PushTransaction,
3371 : : * so as to have someplace to put the SUBBEGIN state.)
3372 : : */
3373 : 22355 : case TBLOCK_SUBBEGIN:
3374 : 22355 : StartSubTransaction();
3375 : 22355 : s->blockState = TBLOCK_SUBINPROGRESS;
3376 : 22355 : break;
3377 : :
3378 : : /*
3379 : : * The user issued a RELEASE command, so we end the current
3380 : : * subtransaction and return to the parent transaction. The parent
3381 : : * might be ended too, so repeat till we find an INPROGRESS
3382 : : * transaction or subtransaction.
3383 : : */
3384 : 268 : case TBLOCK_SUBRELEASE:
3385 : : do
3386 : : {
3387 : 268 : CommitSubTransaction();
3388 : 268 : s = CurrentTransactionState; /* changed by pop */
3389 [ + + ]: 268 : } while (s->blockState == TBLOCK_SUBRELEASE);
3390 : :
3391 : : Assert(s->blockState == TBLOCK_INPROGRESS ||
3392 : : s->blockState == TBLOCK_SUBINPROGRESS);
3393 : 181 : break;
3394 : :
3395 : : /*
3396 : : * The user issued a COMMIT, so we end the current subtransaction
3397 : : * hierarchy and perform final commit. We do this by rolling up
3398 : : * any subtransactions into their parent, which leads to O(N^2)
3399 : : * operations with respect to resource owners - this isn't that
3400 : : * bad until we approach a thousands of savepoints but is
3401 : : * necessary for correctness should after triggers create new
3402 : : * resource owners.
3403 : : */
3404 : 591 : case TBLOCK_SUBCOMMIT:
3405 : : do
3406 : : {
3407 : 591 : CommitSubTransaction();
3408 : 591 : s = CurrentTransactionState; /* changed by pop */
3409 [ + + ]: 591 : } while (s->blockState == TBLOCK_SUBCOMMIT);
3410 : : /* If we had a COMMIT command, finish off the main xact too */
3411 [ + + ]: 502 : if (s->blockState == TBLOCK_END)
3412 : : {
3413 : : Assert(s->parent == NULL);
3414 : 377 : CommitTransaction();
3415 : 360 : s->blockState = TBLOCK_DEFAULT;
3416 [ + + ]: 360 : if (s->chain)
3417 : : {
3418 : 12 : StartTransaction();
3419 : 12 : s->blockState = TBLOCK_INPROGRESS;
3420 : 12 : s->chain = false;
3421 : 12 : RestoreTransactionCharacteristics(&savetc);
3422 : : }
3423 : : }
3424 [ + - ]: 125 : else if (s->blockState == TBLOCK_PREPARE)
3425 : : {
3426 : : Assert(s->parent == NULL);
3427 : 125 : PrepareTransaction();
3428 : 123 : s->blockState = TBLOCK_DEFAULT;
3429 : : }
3430 : : else
3431 [ # # ]: 0 : elog(ERROR, "CommitTransactionCommand: unexpected state %s",
3432 : : BlockStateAsString(s->blockState));
3433 : 483 : break;
3434 : :
3435 : : /*
3436 : : * The current already-failed subtransaction is ending due to a
3437 : : * ROLLBACK or ROLLBACK TO command, so pop it and recursively
3438 : : * examine the parent (which could be in any of several states).
3439 : : * As we need to examine the parent, return false to request the
3440 : : * caller to do the next iteration.
3441 : : */
3442 : 51 : case TBLOCK_SUBABORT_END:
3443 : 51 : CleanupSubTransaction();
3444 : 51 : return false;
3445 : :
3446 : : /*
3447 : : * As above, but it's not dead yet, so abort first.
3448 : : */
3449 : 264 : case TBLOCK_SUBABORT_PENDING:
3450 : 264 : AbortSubTransaction();
3451 : 264 : CleanupSubTransaction();
3452 : 264 : return false;
3453 : :
3454 : : /*
3455 : : * The current subtransaction is the target of a ROLLBACK TO
3456 : : * command. Abort and pop it, then start a new subtransaction
3457 : : * with the same name.
3458 : : */
3459 : 333 : case TBLOCK_SUBRESTART:
3460 : : {
3461 : : char *name;
3462 : : int savepointLevel;
3463 : :
3464 : : /* save name and keep Cleanup from freeing it */
3465 : 333 : name = s->name;
3466 : 333 : s->name = NULL;
3467 : 333 : savepointLevel = s->savepointLevel;
3468 : :
3469 : 333 : AbortSubTransaction();
3470 : 333 : CleanupSubTransaction();
3471 : :
3472 : 333 : DefineSavepoint(NULL);
3473 : 333 : s = CurrentTransactionState; /* changed by push */
3474 : 333 : s->name = name;
3475 : 333 : s->savepointLevel = savepointLevel;
3476 : :
3477 : : /* This is the same as TBLOCK_SUBBEGIN case */
3478 : : Assert(s->blockState == TBLOCK_SUBBEGIN);
3479 : 333 : StartSubTransaction();
3480 : 333 : s->blockState = TBLOCK_SUBINPROGRESS;
3481 : : }
3482 : 333 : break;
3483 : :
3484 : : /*
3485 : : * Same as above, but the subtransaction had already failed, so we
3486 : : * don't need AbortSubTransaction.
3487 : : */
3488 : 169 : case TBLOCK_SUBABORT_RESTART:
3489 : : {
3490 : : char *name;
3491 : : int savepointLevel;
3492 : :
3493 : : /* save name and keep Cleanup from freeing it */
3494 : 169 : name = s->name;
3495 : 169 : s->name = NULL;
3496 : 169 : savepointLevel = s->savepointLevel;
3497 : :
3498 : 169 : CleanupSubTransaction();
3499 : :
3500 : 169 : DefineSavepoint(NULL);
3501 : 169 : s = CurrentTransactionState; /* changed by push */
3502 : 169 : s->name = name;
3503 : 169 : s->savepointLevel = savepointLevel;
3504 : :
3505 : : /* This is the same as TBLOCK_SUBBEGIN case */
3506 : : Assert(s->blockState == TBLOCK_SUBBEGIN);
3507 : 169 : StartSubTransaction();
3508 : 169 : s->blockState = TBLOCK_SUBINPROGRESS;
3509 : : }
3510 : 169 : break;
3511 : : }
3512 : :
3513 : : /* Done, no more iterations required */
3514 : 728962 : return true;
3515 : : }
3516 : :
3517 : : /*
3518 : : * AbortCurrentTransaction -- a wrapper function handling the
3519 : : * loop over subtransactions to avoid potentially dangerous recursion in
3520 : : * AbortCurrentTransactionInternal().
3521 : : */
3522 : : void
3523 : 34745 : AbortCurrentTransaction(void)
3524 : : {
3525 : : /*
3526 : : * Repeatedly call AbortCurrentTransactionInternal() until all the work is
3527 : : * done.
3528 : : */
3529 [ - + ]: 34745 : while (!AbortCurrentTransactionInternal())
3530 : : {
3531 : : }
3532 : 34745 : }
3533 : :
3534 : : /*
3535 : : * AbortCurrentTransactionInternal - a function doing an iteration of work
3536 : : * regarding handling the current transaction abort. In the case of
3537 : : * subtransactions more than one iterations could be required. Returns
3538 : : * true when no more iterations required, false otherwise.
3539 : : */
3540 : : static bool
3541 : 34745 : AbortCurrentTransactionInternal(void)
3542 : : {
3543 : 34745 : TransactionState s = CurrentTransactionState;
3544 : :
3545 [ + + - + : 34745 : switch (s->blockState)
+ + - - +
+ - - - ]
3546 : : {
3547 : 52 : case TBLOCK_DEFAULT:
3548 [ - + ]: 52 : if (s->state == TRANS_DEFAULT)
3549 : : {
3550 : : /* we are idle, so nothing to do */
3551 : : }
3552 : : else
3553 : : {
3554 : : /*
3555 : : * We can get here after an error during transaction start
3556 : : * (state will be TRANS_START). Need to clean up the
3557 : : * incompletely started transaction. First, adjust the
3558 : : * low-level state to suppress warning message from
3559 : : * AbortTransaction.
3560 : : */
3561 [ # # ]: 0 : if (s->state == TRANS_START)
3562 : 0 : s->state = TRANS_INPROGRESS;
3563 : 0 : AbortTransaction();
3564 : 0 : CleanupTransaction();
3565 : : }
3566 : 52 : break;
3567 : :
3568 : : /*
3569 : : * If we aren't in a transaction block, we just do the basic abort
3570 : : * & cleanup transaction. For this purpose, we treat an implicit
3571 : : * transaction block as if it were a simple statement.
3572 : : */
3573 : 32146 : case TBLOCK_STARTED:
3574 : : case TBLOCK_IMPLICIT_INPROGRESS:
3575 : 32146 : AbortTransaction();
3576 : 32146 : CleanupTransaction();
3577 : 32146 : s->blockState = TBLOCK_DEFAULT;
3578 : 32146 : break;
3579 : :
3580 : : /*
3581 : : * If we are in TBLOCK_BEGIN it means something screwed up right
3582 : : * after reading "BEGIN TRANSACTION". We assume that the user
3583 : : * will interpret the error as meaning the BEGIN failed to get him
3584 : : * into a transaction block, so we should abort and return to idle
3585 : : * state.
3586 : : */
3587 : 0 : case TBLOCK_BEGIN:
3588 : 0 : AbortTransaction();
3589 : 0 : CleanupTransaction();
3590 : 0 : s->blockState = TBLOCK_DEFAULT;
3591 : 0 : break;
3592 : :
3593 : : /*
3594 : : * We are somewhere in a transaction block and we've gotten a
3595 : : * failure, so we abort the transaction and set up the persistent
3596 : : * ABORT state. We will stay in ABORT until we get a ROLLBACK.
3597 : : */
3598 : 908 : case TBLOCK_INPROGRESS:
3599 : : case TBLOCK_PARALLEL_INPROGRESS:
3600 : 908 : AbortTransaction();
3601 : 908 : s->blockState = TBLOCK_ABORT;
3602 : : /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
3603 : 908 : break;
3604 : :
3605 : : /*
3606 : : * Here, we failed while trying to COMMIT. Clean up the
3607 : : * transaction and return to idle state (we do not want to stay in
3608 : : * the transaction).
3609 : : */
3610 : 271 : case TBLOCK_END:
3611 : 271 : AbortTransaction();
3612 : 271 : CleanupTransaction();
3613 : 271 : s->blockState = TBLOCK_DEFAULT;
3614 : 271 : break;
3615 : :
3616 : : /*
3617 : : * Here, we are already in an aborted transaction state and are
3618 : : * waiting for a ROLLBACK, but for some reason we failed again! So
3619 : : * we just remain in the abort state.
3620 : : */
3621 : 63 : case TBLOCK_ABORT:
3622 : : case TBLOCK_SUBABORT:
3623 : 63 : break;
3624 : :
3625 : : /*
3626 : : * We are in a failed transaction and we got the ROLLBACK command.
3627 : : * We have already aborted, we just need to cleanup and go to idle
3628 : : * state.
3629 : : */
3630 : 0 : case TBLOCK_ABORT_END:
3631 : 0 : CleanupTransaction();
3632 : 0 : s->blockState = TBLOCK_DEFAULT;
3633 : 0 : break;
3634 : :
3635 : : /*
3636 : : * We are in a live transaction and we got a ROLLBACK command.
3637 : : * Abort, cleanup, go to idle state.
3638 : : */
3639 : 0 : case TBLOCK_ABORT_PENDING:
3640 : 0 : AbortTransaction();
3641 : 0 : CleanupTransaction();
3642 : 0 : s->blockState = TBLOCK_DEFAULT;
3643 : 0 : break;
3644 : :
3645 : : /*
3646 : : * Here, we failed while trying to PREPARE. Clean up the
3647 : : * transaction and return to idle state (we do not want to stay in
3648 : : * the transaction).
3649 : : */
3650 : 64 : case TBLOCK_PREPARE:
3651 : 64 : AbortTransaction();
3652 : 64 : CleanupTransaction();
3653 : 64 : s->blockState = TBLOCK_DEFAULT;
3654 : 64 : break;
3655 : :
3656 : : /*
3657 : : * We got an error inside a subtransaction. Abort just the
3658 : : * subtransaction, and go to the persistent SUBABORT state until
3659 : : * we get ROLLBACK.
3660 : : */
3661 : 1241 : case TBLOCK_SUBINPROGRESS:
3662 : 1241 : AbortSubTransaction();
3663 : 1241 : s->blockState = TBLOCK_SUBABORT;
3664 : 1241 : break;
3665 : :
3666 : : /*
3667 : : * If we failed while trying to create a subtransaction, clean up
3668 : : * the broken subtransaction and abort the parent. The same
3669 : : * applies if we get a failure while ending a subtransaction. As
3670 : : * we need to abort the parent, return false to request the caller
3671 : : * to do the next iteration.
3672 : : */
3673 : 0 : case TBLOCK_SUBBEGIN:
3674 : : case TBLOCK_SUBRELEASE:
3675 : : case TBLOCK_SUBCOMMIT:
3676 : : case TBLOCK_SUBABORT_PENDING:
3677 : : case TBLOCK_SUBRESTART:
3678 : 0 : AbortSubTransaction();
3679 : 0 : CleanupSubTransaction();
3680 : 0 : return false;
3681 : :
3682 : : /*
3683 : : * Same as above, except the Abort() was already done.
3684 : : */
3685 : 0 : case TBLOCK_SUBABORT_END:
3686 : : case TBLOCK_SUBABORT_RESTART:
3687 : 0 : CleanupSubTransaction();
3688 : 0 : return false;
3689 : : }
3690 : :
3691 : : /* Done, no more iterations required */
3692 : 34745 : return true;
3693 : : }
3694 : :
3695 : : /*
3696 : : * PreventInTransactionBlock
3697 : : *
3698 : : * This routine is to be called by statements that must not run inside
3699 : : * a transaction block, typically because they have non-rollback-able
3700 : : * side effects or do internal commits.
3701 : : *
3702 : : * If this routine completes successfully, then the calling statement is
3703 : : * guaranteed that if it completes without error, its results will be
3704 : : * committed immediately.
3705 : : *
3706 : : * If we have already started a transaction block, issue an error; also issue
3707 : : * an error if we appear to be running inside a user-defined function (which
3708 : : * could issue more commands and possibly cause a failure after the statement
3709 : : * completes). Subtransactions are verboten too.
3710 : : *
3711 : : * We must also set XACT_FLAGS_NEEDIMMEDIATECOMMIT in MyXactFlags, to ensure
3712 : : * that postgres.c follows through by committing after the statement is done.
3713 : : *
3714 : : * isTopLevel: passed down from ProcessUtility to determine whether we are
3715 : : * inside a function. (We will always fail if this is false, but it's
3716 : : * convenient to centralize the check here instead of making callers do it.)
3717 : : * stmtType: statement type name, for error messages.
3718 : : */
3719 : : void
3720 : 116962 : PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
3721 : : {
3722 : : /*
3723 : : * xact block already started?
3724 : : */
3725 [ + + ]: 116962 : if (IsTransactionBlock())
3726 [ + - ]: 82 : ereport(ERROR,
3727 : : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
3728 : : /* translator: %s represents an SQL statement name */
3729 : : errmsg("%s cannot run inside a transaction block",
3730 : : stmtType)));
3731 : :
3732 : : /*
3733 : : * subtransaction?
3734 : : */
3735 [ - + ]: 116880 : if (IsSubTransaction())
3736 [ # # ]: 0 : ereport(ERROR,
3737 : : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
3738 : : /* translator: %s represents an SQL statement name */
3739 : : errmsg("%s cannot run inside a subtransaction",
3740 : : stmtType)));
3741 : :
3742 : : /*
3743 : : * inside a function call?
3744 : : */
3745 [ + + ]: 116880 : if (!isTopLevel)
3746 [ + - ]: 8 : ereport(ERROR,
3747 : : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
3748 : : /* translator: %s represents an SQL statement name */
3749 : : errmsg("%s cannot be executed from a function or procedure",
3750 : : stmtType)));
3751 : :
3752 : : /* If we got past IsTransactionBlock test, should be in default state */
3753 [ + + ]: 116872 : if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
3754 [ - + ]: 115790 : CurrentTransactionState->blockState != TBLOCK_STARTED)
3755 [ # # ]: 0 : elog(FATAL, "cannot prevent transaction chain");
3756 : :
3757 : : /* All okay. Set the flag to make sure the right thing happens later. */
3758 : 116872 : MyXactFlags |= XACT_FLAGS_NEEDIMMEDIATECOMMIT;
3759 : 116872 : }
3760 : :
3761 : : /*
3762 : : * WarnNoTransactionBlock
3763 : : * RequireTransactionBlock
3764 : : *
3765 : : * These two functions allow for warnings or errors if a command is executed
3766 : : * outside of a transaction block. This is useful for commands that have no
3767 : : * effects that persist past transaction end (and so calling them outside a
3768 : : * transaction block is presumably an error). DECLARE CURSOR is an example.
3769 : : * While top-level transaction control commands (BEGIN/COMMIT/ABORT) and SET
3770 : : * that have no effect issue warnings, all other no-effect commands generate
3771 : : * errors.
3772 : : *
3773 : : * If we appear to be running inside a user-defined function, we do not
3774 : : * issue anything, since the function could issue more commands that make
3775 : : * use of the current statement's results. Likewise subtransactions.
3776 : : * Thus these are inverses for PreventInTransactionBlock.
3777 : : *
3778 : : * isTopLevel: passed down from ProcessUtility to determine whether we are
3779 : : * inside a function.
3780 : : * stmtType: statement type name, for warning or error messages.
3781 : : */
3782 : : void
3783 : 1492 : WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
3784 : : {
3785 : 1492 : CheckTransactionBlock(isTopLevel, false, stmtType);
3786 : 1492 : }
3787 : :
3788 : : void
3789 : 5140 : RequireTransactionBlock(bool isTopLevel, const char *stmtType)
3790 : : {
3791 : 5140 : CheckTransactionBlock(isTopLevel, true, stmtType);
3792 : 5117 : }
3793 : :
3794 : : /*
3795 : : * This is the implementation of the above two.
3796 : : */
3797 : : static void
3798 : 6632 : CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
3799 : : {
3800 : : /*
3801 : : * xact block already started?
3802 : : */
3803 [ + + ]: 6632 : if (IsTransactionBlock())
3804 : 6513 : return;
3805 : :
3806 : : /*
3807 : : * subtransaction?
3808 : : */
3809 [ - + ]: 119 : if (IsSubTransaction())
3810 : 0 : return;
3811 : :
3812 : : /*
3813 : : * inside a function call?
3814 : : */
3815 [ + + ]: 119 : if (!isTopLevel)
3816 : 82 : return;
3817 : :
3818 [ + + + - ]: 37 : ereport(throwError ? ERROR : WARNING,
3819 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3820 : : /* translator: %s represents an SQL statement name */
3821 : : errmsg("%s can only be used in transaction blocks",
3822 : : stmtType)));
3823 : : }
3824 : :
3825 : : /*
3826 : : * IsInTransactionBlock
3827 : : *
3828 : : * This routine is for statements that need to behave differently inside
3829 : : * a transaction block than when running as single commands. ANALYZE is
3830 : : * currently the only example.
3831 : : *
3832 : : * If this routine returns "false", then the calling statement is allowed
3833 : : * to perform internal transaction-commit-and-start cycles; there is not a
3834 : : * risk of messing up any transaction already in progress. (Note that this
3835 : : * is not the identical guarantee provided by PreventInTransactionBlock,
3836 : : * since we will not force a post-statement commit.)
3837 : : *
3838 : : * isTopLevel: passed down from ProcessUtility to determine whether we are
3839 : : * inside a function.
3840 : : */
3841 : : bool
3842 : 3296 : IsInTransactionBlock(bool isTopLevel)
3843 : : {
3844 : : /*
3845 : : * Return true on same conditions that would make
3846 : : * PreventInTransactionBlock error out
3847 : : */
3848 [ + + ]: 3296 : if (IsTransactionBlock())
3849 : 102 : return true;
3850 : :
3851 [ - + ]: 3194 : if (IsSubTransaction())
3852 : 0 : return true;
3853 : :
3854 [ + + ]: 3194 : if (!isTopLevel)
3855 : 74 : return true;
3856 : :
3857 [ + - ]: 3120 : if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
3858 [ - + ]: 3120 : CurrentTransactionState->blockState != TBLOCK_STARTED)
3859 : 0 : return true;
3860 : :
3861 : 3120 : return false;
3862 : : }
3863 : :
3864 : :
3865 : : /*
3866 : : * Register or deregister callback functions for start- and end-of-xact
3867 : : * operations.
3868 : : *
3869 : : * These functions are intended for use by dynamically loaded modules.
3870 : : * For built-in modules we generally just hardwire the appropriate calls
3871 : : * (mainly because it's easier to control the order that way, where needed).
3872 : : *
3873 : : * At transaction end, the callback occurs post-commit or post-abort, so the
3874 : : * callback functions can only do noncritical cleanup.
3875 : : */
3876 : : void
3877 : 2358 : RegisterXactCallback(XactCallback callback, void *arg)
3878 : : {
3879 : : XactCallbackItem *item;
3880 : :
3881 : : item = (XactCallbackItem *)
3882 : 2358 : MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
3883 : 2358 : item->callback = callback;
3884 : 2358 : item->arg = arg;
3885 : 2358 : item->next = Xact_callbacks;
3886 : 2358 : Xact_callbacks = item;
3887 : 2358 : }
3888 : :
3889 : : void
3890 : 0 : UnregisterXactCallback(XactCallback callback, void *arg)
3891 : : {
3892 : : XactCallbackItem *item;
3893 : : XactCallbackItem *prev;
3894 : :
3895 : 0 : prev = NULL;
3896 [ # # ]: 0 : for (item = Xact_callbacks; item; prev = item, item = item->next)
3897 : : {
3898 [ # # # # ]: 0 : if (item->callback == callback && item->arg == arg)
3899 : : {
3900 [ # # ]: 0 : if (prev)
3901 : 0 : prev->next = item->next;
3902 : : else
3903 : 0 : Xact_callbacks = item->next;
3904 : 0 : pfree(item);
3905 : 0 : break;
3906 : : }
3907 : : }
3908 : 0 : }
3909 : :
3910 : : static void
3911 : 1264257 : CallXactCallbacks(XactEvent event)
3912 : : {
3913 : : XactCallbackItem *item;
3914 : : XactCallbackItem *next;
3915 : :
3916 [ + + ]: 1469437 : for (item = Xact_callbacks; item; item = next)
3917 : : {
3918 : : /* allow callbacks to unregister themselves when called */
3919 : 205182 : next = item->next;
3920 : 205182 : item->callback(event, item->arg);
3921 : : }
3922 : 1264255 : }
3923 : :
3924 : :
3925 : : /*
3926 : : * Register or deregister callback functions for start- and end-of-subxact
3927 : : * operations.
3928 : : *
3929 : : * Pretty much same as above, but for subtransaction events.
3930 : : *
3931 : : * At subtransaction end, the callback occurs post-subcommit or post-subabort,
3932 : : * so the callback functions can only do noncritical cleanup. At
3933 : : * subtransaction start, the callback is called when the subtransaction has
3934 : : * finished initializing.
3935 : : */
3936 : : void
3937 : 2358 : RegisterSubXactCallback(SubXactCallback callback, void *arg)
3938 : : {
3939 : : SubXactCallbackItem *item;
3940 : :
3941 : : item = (SubXactCallbackItem *)
3942 : 2358 : MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
3943 : 2358 : item->callback = callback;
3944 : 2358 : item->arg = arg;
3945 : 2358 : item->next = SubXact_callbacks;
3946 : 2358 : SubXact_callbacks = item;
3947 : 2358 : }
3948 : :
3949 : : void
3950 : 0 : UnregisterSubXactCallback(SubXactCallback callback, void *arg)
3951 : : {
3952 : : SubXactCallbackItem *item;
3953 : : SubXactCallbackItem *prev;
3954 : :
3955 : 0 : prev = NULL;
3956 [ # # ]: 0 : for (item = SubXact_callbacks; item; prev = item, item = item->next)
3957 : : {
3958 [ # # # # ]: 0 : if (item->callback == callback && item->arg == arg)
3959 : : {
3960 [ # # ]: 0 : if (prev)
3961 : 0 : prev->next = item->next;
3962 : : else
3963 : 0 : SubXact_callbacks = item->next;
3964 : 0 : pfree(item);
3965 : 0 : break;
3966 : : }
3967 : : }
3968 : 0 : }
3969 : :
3970 : : static void
3971 : 63091 : CallSubXactCallbacks(SubXactEvent event,
3972 : : SubTransactionId mySubid,
3973 : : SubTransactionId parentSubid)
3974 : : {
3975 : : SubXactCallbackItem *item;
3976 : : SubXactCallbackItem *next;
3977 : :
3978 [ + + ]: 120150 : for (item = SubXact_callbacks; item; item = next)
3979 : : {
3980 : : /* allow callbacks to unregister themselves when called */
3981 : 57059 : next = item->next;
3982 : 57059 : item->callback(event, mySubid, parentSubid, item->arg);
3983 : : }
3984 : 63091 : }
3985 : :
3986 : :
3987 : : /* ----------------------------------------------------------------
3988 : : * transaction block support
3989 : : * ----------------------------------------------------------------
3990 : : */
3991 : :
3992 : : /*
3993 : : * BeginTransactionBlock
3994 : : * This executes a BEGIN command.
3995 : : */
3996 : : void
3997 : 12568 : BeginTransactionBlock(void)
3998 : : {
3999 : 12568 : TransactionState s = CurrentTransactionState;
4000 : :
4001 [ + + - - : 12568 : switch (s->blockState)
- ]
4002 : : {
4003 : : /*
4004 : : * We are not inside a transaction block, so allow one to begin.
4005 : : */
4006 : 12059 : case TBLOCK_STARTED:
4007 : 12059 : s->blockState = TBLOCK_BEGIN;
4008 : 12059 : break;
4009 : :
4010 : : /*
4011 : : * BEGIN converts an implicit transaction block to a regular one.
4012 : : * (Note that we allow this even if we've already done some
4013 : : * commands, which is a bit odd but matches historical practice.)
4014 : : */
4015 : 509 : case TBLOCK_IMPLICIT_INPROGRESS:
4016 : 509 : s->blockState = TBLOCK_BEGIN;
4017 : 509 : break;
4018 : :
4019 : : /*
4020 : : * Already a transaction block in progress.
4021 : : */
4022 : 0 : case TBLOCK_INPROGRESS:
4023 : : case TBLOCK_PARALLEL_INPROGRESS:
4024 : : case TBLOCK_SUBINPROGRESS:
4025 : : case TBLOCK_ABORT:
4026 : : case TBLOCK_SUBABORT:
4027 [ # # ]: 0 : ereport(WARNING,
4028 : : (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
4029 : : errmsg("there is already a transaction in progress")));
4030 : 0 : break;
4031 : :
4032 : : /* These cases are invalid. */
4033 : 0 : case TBLOCK_DEFAULT:
4034 : : case TBLOCK_BEGIN:
4035 : : case TBLOCK_SUBBEGIN:
4036 : : case TBLOCK_END:
4037 : : case TBLOCK_SUBRELEASE:
4038 : : case TBLOCK_SUBCOMMIT:
4039 : : case TBLOCK_ABORT_END:
4040 : : case TBLOCK_SUBABORT_END:
4041 : : case TBLOCK_ABORT_PENDING:
4042 : : case TBLOCK_SUBABORT_PENDING:
4043 : : case TBLOCK_SUBRESTART:
4044 : : case TBLOCK_SUBABORT_RESTART:
4045 : : case TBLOCK_PREPARE:
4046 [ # # ]: 0 : elog(FATAL, "BeginTransactionBlock: unexpected state %s",
4047 : : BlockStateAsString(s->blockState));
4048 : : break;
4049 : : }
4050 : 12568 : }
4051 : :
4052 : : /*
4053 : : * PrepareTransactionBlock
4054 : : * This executes a PREPARE command.
4055 : : *
4056 : : * Since PREPARE may actually do a ROLLBACK, the result indicates what
4057 : : * happened: true for PREPARE, false for ROLLBACK.
4058 : : *
4059 : : * Note that we don't actually do anything here except change blockState.
4060 : : * The real work will be done in the upcoming PrepareTransaction().
4061 : : * We do it this way because it's not convenient to change memory context,
4062 : : * resource owner, etc while executing inside a Portal.
4063 : : */
4064 : : bool
4065 : 397 : PrepareTransactionBlock(const char *gid)
4066 : : {
4067 : : TransactionState s;
4068 : : bool result;
4069 : :
4070 : : /* Set up to commit the current transaction */
4071 : 397 : result = EndTransactionBlock(false);
4072 : :
4073 : : /* If successful, change outer tblock state to PREPARE */
4074 [ + + ]: 397 : if (result)
4075 : : {
4076 : 395 : s = CurrentTransactionState;
4077 : :
4078 [ + + ]: 530 : while (s->parent != NULL)
4079 : 135 : s = s->parent;
4080 : :
4081 [ + - ]: 395 : if (s->blockState == TBLOCK_END)
4082 : : {
4083 : : /* Save GID where PrepareTransaction can find it again */
4084 : 395 : prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
4085 : :
4086 : 395 : s->blockState = TBLOCK_PREPARE;
4087 : : }
4088 : : else
4089 : : {
4090 : : /*
4091 : : * ignore case where we are not in a transaction;
4092 : : * EndTransactionBlock already issued a warning.
4093 : : */
4094 : : Assert(s->blockState == TBLOCK_STARTED ||
4095 : : s->blockState == TBLOCK_IMPLICIT_INPROGRESS);
4096 : : /* Don't send back a PREPARE result tag... */
4097 : 0 : result = false;
4098 : : }
4099 : : }
4100 : :
4101 : 397 : return result;
4102 : : }
4103 : :
4104 : : /*
4105 : : * EndTransactionBlock
4106 : : * This executes a COMMIT command.
4107 : : *
4108 : : * Since COMMIT may actually do a ROLLBACK, the result indicates what
4109 : : * happened: true for COMMIT, false for ROLLBACK.
4110 : : *
4111 : : * Note that we don't actually do anything here except change blockState.
4112 : : * The real work will be done in the upcoming CommitTransactionCommand().
4113 : : * We do it this way because it's not convenient to change memory context,
4114 : : * resource owner, etc while executing inside a Portal.
4115 : : */
4116 : : bool
4117 : 10096 : EndTransactionBlock(bool chain)
4118 : : {
4119 : 10096 : TransactionState s = CurrentTransactionState;
4120 : 10096 : bool result = false;
4121 : :
4122 [ + + + + : 10096 : switch (s->blockState)
+ + - -
- ]
4123 : : {
4124 : : /*
4125 : : * We are in a transaction block, so tell CommitTransactionCommand
4126 : : * to COMMIT.
4127 : : */
4128 : 9064 : case TBLOCK_INPROGRESS:
4129 : 9064 : s->blockState = TBLOCK_END;
4130 : 9064 : result = true;
4131 : 9064 : break;
4132 : :
4133 : : /*
4134 : : * We are in an implicit transaction block. If AND CHAIN was
4135 : : * specified, error. Otherwise commit, but issue a warning
4136 : : * because there was no explicit BEGIN before this.
4137 : : */
4138 : 32 : case TBLOCK_IMPLICIT_INPROGRESS:
4139 [ + + ]: 32 : if (chain)
4140 [ + - ]: 16 : ereport(ERROR,
4141 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4142 : : /* translator: %s represents an SQL statement name */
4143 : : errmsg("%s can only be used in transaction blocks",
4144 : : "COMMIT AND CHAIN")));
4145 : : else
4146 [ + - ]: 16 : ereport(WARNING,
4147 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4148 : : errmsg("there is no transaction in progress")));
4149 : 16 : s->blockState = TBLOCK_END;
4150 : 16 : result = true;
4151 : 16 : break;
4152 : :
4153 : : /*
4154 : : * We are in a failed transaction block. Tell
4155 : : * CommitTransactionCommand it's time to exit the block.
4156 : : */
4157 : 444 : case TBLOCK_ABORT:
4158 : 444 : s->blockState = TBLOCK_ABORT_END;
4159 : 444 : break;
4160 : :
4161 : : /*
4162 : : * We are in a live subtransaction block. Set up to subcommit all
4163 : : * open subtransactions and then commit the main transaction.
4164 : : */
4165 : 502 : case TBLOCK_SUBINPROGRESS:
4166 [ + + ]: 1093 : while (s->parent != NULL)
4167 : : {
4168 [ + - ]: 591 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4169 : 591 : s->blockState = TBLOCK_SUBCOMMIT;
4170 : : else
4171 [ # # ]: 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4172 : : BlockStateAsString(s->blockState));
4173 : 591 : s = s->parent;
4174 : : }
4175 [ + - ]: 502 : if (s->blockState == TBLOCK_INPROGRESS)
4176 : 502 : s->blockState = TBLOCK_END;
4177 : : else
4178 [ # # ]: 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4179 : : BlockStateAsString(s->blockState));
4180 : 502 : result = true;
4181 : 502 : break;
4182 : :
4183 : : /*
4184 : : * Here we are inside an aborted subtransaction. Treat the COMMIT
4185 : : * as ROLLBACK: set up to abort everything and exit the main
4186 : : * transaction.
4187 : : */
4188 : 38 : case TBLOCK_SUBABORT:
4189 [ + + ]: 76 : while (s->parent != NULL)
4190 : : {
4191 [ - + ]: 38 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4192 : 0 : s->blockState = TBLOCK_SUBABORT_PENDING;
4193 [ + - ]: 38 : else if (s->blockState == TBLOCK_SUBABORT)
4194 : 38 : s->blockState = TBLOCK_SUBABORT_END;
4195 : : else
4196 [ # # ]: 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4197 : : BlockStateAsString(s->blockState));
4198 : 38 : s = s->parent;
4199 : : }
4200 [ + - ]: 38 : if (s->blockState == TBLOCK_INPROGRESS)
4201 : 38 : s->blockState = TBLOCK_ABORT_PENDING;
4202 [ # # ]: 0 : else if (s->blockState == TBLOCK_ABORT)
4203 : 0 : s->blockState = TBLOCK_ABORT_END;
4204 : : else
4205 [ # # ]: 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4206 : : BlockStateAsString(s->blockState));
4207 : 38 : break;
4208 : :
4209 : : /*
4210 : : * The user issued COMMIT when not inside a transaction. For
4211 : : * COMMIT without CHAIN, issue a WARNING, staying in
4212 : : * TBLOCK_STARTED state. The upcoming call to
4213 : : * CommitTransactionCommand() will then close the transaction and
4214 : : * put us back into the default state. For COMMIT AND CHAIN,
4215 : : * error.
4216 : : */
4217 : 16 : case TBLOCK_STARTED:
4218 [ + + ]: 16 : if (chain)
4219 [ + - ]: 4 : ereport(ERROR,
4220 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4221 : : /* translator: %s represents an SQL statement name */
4222 : : errmsg("%s can only be used in transaction blocks",
4223 : : "COMMIT AND CHAIN")));
4224 : : else
4225 [ + - ]: 12 : ereport(WARNING,
4226 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4227 : : errmsg("there is no transaction in progress")));
4228 : 12 : result = true;
4229 : 12 : break;
4230 : :
4231 : : /*
4232 : : * The user issued a COMMIT that somehow ran inside a parallel
4233 : : * worker. We can't cope with that.
4234 : : */
4235 : 0 : case TBLOCK_PARALLEL_INPROGRESS:
4236 [ # # ]: 0 : ereport(FATAL,
4237 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4238 : : errmsg("cannot commit during a parallel operation")));
4239 : : break;
4240 : :
4241 : : /* These cases are invalid. */
4242 : 0 : case TBLOCK_DEFAULT:
4243 : : case TBLOCK_BEGIN:
4244 : : case TBLOCK_SUBBEGIN:
4245 : : case TBLOCK_END:
4246 : : case TBLOCK_SUBRELEASE:
4247 : : case TBLOCK_SUBCOMMIT:
4248 : : case TBLOCK_ABORT_END:
4249 : : case TBLOCK_SUBABORT_END:
4250 : : case TBLOCK_ABORT_PENDING:
4251 : : case TBLOCK_SUBABORT_PENDING:
4252 : : case TBLOCK_SUBRESTART:
4253 : : case TBLOCK_SUBABORT_RESTART:
4254 : : case TBLOCK_PREPARE:
4255 [ # # ]: 0 : elog(FATAL, "EndTransactionBlock: unexpected state %s",
4256 : : BlockStateAsString(s->blockState));
4257 : : break;
4258 : : }
4259 : :
4260 : : Assert(s->blockState == TBLOCK_STARTED ||
4261 : : s->blockState == TBLOCK_END ||
4262 : : s->blockState == TBLOCK_ABORT_END ||
4263 : : s->blockState == TBLOCK_ABORT_PENDING);
4264 : :
4265 : 10076 : s->chain = chain;
4266 : :
4267 : 10076 : return result;
4268 : : }
4269 : :
4270 : : /*
4271 : : * UserAbortTransactionBlock
4272 : : * This executes a ROLLBACK command.
4273 : : *
4274 : : * As above, we don't actually do anything here except change blockState.
4275 : : */
4276 : : void
4277 : 2273 : UserAbortTransactionBlock(bool chain)
4278 : : {
4279 : 2273 : TransactionState s = CurrentTransactionState;
4280 : :
4281 [ + + + + : 2273 : switch (s->blockState)
- - - ]
4282 : : {
4283 : : /*
4284 : : * We are inside a transaction block and we got a ROLLBACK command
4285 : : * from the user, so tell CommitTransactionCommand to abort and
4286 : : * exit the transaction block.
4287 : : */
4288 : 1692 : case TBLOCK_INPROGRESS:
4289 : 1692 : s->blockState = TBLOCK_ABORT_PENDING;
4290 : 1692 : break;
4291 : :
4292 : : /*
4293 : : * We are inside a failed transaction block and we got a ROLLBACK
4294 : : * command from the user. Abort processing is already done, so
4295 : : * CommitTransactionCommand just has to cleanup and go back to
4296 : : * idle state.
4297 : : */
4298 : 447 : case TBLOCK_ABORT:
4299 : 447 : s->blockState = TBLOCK_ABORT_END;
4300 : 447 : break;
4301 : :
4302 : : /*
4303 : : * We are inside a subtransaction. Mark everything up to top
4304 : : * level as exitable.
4305 : : */
4306 : 83 : case TBLOCK_SUBINPROGRESS:
4307 : : case TBLOCK_SUBABORT:
4308 [ + + ]: 322 : while (s->parent != NULL)
4309 : : {
4310 [ + + ]: 239 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4311 : 226 : s->blockState = TBLOCK_SUBABORT_PENDING;
4312 [ + - ]: 13 : else if (s->blockState == TBLOCK_SUBABORT)
4313 : 13 : s->blockState = TBLOCK_SUBABORT_END;
4314 : : else
4315 [ # # ]: 0 : elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
4316 : : BlockStateAsString(s->blockState));
4317 : 239 : s = s->parent;
4318 : : }
4319 [ + - ]: 83 : if (s->blockState == TBLOCK_INPROGRESS)
4320 : 83 : s->blockState = TBLOCK_ABORT_PENDING;
4321 [ # # ]: 0 : else if (s->blockState == TBLOCK_ABORT)
4322 : 0 : s->blockState = TBLOCK_ABORT_END;
4323 : : else
4324 [ # # ]: 0 : elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
4325 : : BlockStateAsString(s->blockState));
4326 : 83 : break;
4327 : :
4328 : : /*
4329 : : * The user issued ABORT when not inside a transaction. For
4330 : : * ROLLBACK without CHAIN, issue a WARNING and go to abort state.
4331 : : * The upcoming call to CommitTransactionCommand() will then put
4332 : : * us back into the default state. For ROLLBACK AND CHAIN, error.
4333 : : *
4334 : : * We do the same thing with ABORT inside an implicit transaction,
4335 : : * although in this case we might be rolling back actual database
4336 : : * state changes. (It's debatable whether we should issue a
4337 : : * WARNING in this case, but we have done so historically.)
4338 : : */
4339 : 51 : case TBLOCK_STARTED:
4340 : : case TBLOCK_IMPLICIT_INPROGRESS:
4341 [ + + ]: 51 : if (chain)
4342 [ + - ]: 20 : ereport(ERROR,
4343 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4344 : : /* translator: %s represents an SQL statement name */
4345 : : errmsg("%s can only be used in transaction blocks",
4346 : : "ROLLBACK AND CHAIN")));
4347 : : else
4348 [ + - ]: 31 : ereport(WARNING,
4349 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4350 : : errmsg("there is no transaction in progress")));
4351 : 31 : s->blockState = TBLOCK_ABORT_PENDING;
4352 : 31 : break;
4353 : :
4354 : : /*
4355 : : * The user issued an ABORT that somehow ran inside a parallel
4356 : : * worker. We can't cope with that.
4357 : : */
4358 : 0 : case TBLOCK_PARALLEL_INPROGRESS:
4359 [ # # ]: 0 : ereport(FATAL,
4360 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4361 : : errmsg("cannot abort during a parallel operation")));
4362 : : break;
4363 : :
4364 : : /* These cases are invalid. */
4365 : 0 : case TBLOCK_DEFAULT:
4366 : : case TBLOCK_BEGIN:
4367 : : case TBLOCK_SUBBEGIN:
4368 : : case TBLOCK_END:
4369 : : case TBLOCK_SUBRELEASE:
4370 : : case TBLOCK_SUBCOMMIT:
4371 : : case TBLOCK_ABORT_END:
4372 : : case TBLOCK_SUBABORT_END:
4373 : : case TBLOCK_ABORT_PENDING:
4374 : : case TBLOCK_SUBABORT_PENDING:
4375 : : case TBLOCK_SUBRESTART:
4376 : : case TBLOCK_SUBABORT_RESTART:
4377 : : case TBLOCK_PREPARE:
4378 [ # # ]: 0 : elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
4379 : : BlockStateAsString(s->blockState));
4380 : : break;
4381 : : }
4382 : :
4383 : : Assert(s->blockState == TBLOCK_ABORT_END ||
4384 : : s->blockState == TBLOCK_ABORT_PENDING);
4385 : :
4386 : 2253 : s->chain = chain;
4387 : 2253 : }
4388 : :
4389 : : /*
4390 : : * BeginImplicitTransactionBlock
4391 : : * Start an implicit transaction block if we're not already in one.
4392 : : *
4393 : : * Unlike BeginTransactionBlock, this is called directly from the main loop
4394 : : * in postgres.c, not within a Portal. So we can just change blockState
4395 : : * without a lot of ceremony. We do not expect caller to do
4396 : : * CommitTransactionCommand/StartTransactionCommand.
4397 : : */
4398 : : void
4399 : 49281 : BeginImplicitTransactionBlock(void)
4400 : : {
4401 : 49281 : TransactionState s = CurrentTransactionState;
4402 : :
4403 : : /*
4404 : : * If we are in STARTED state (that is, no transaction block is open),
4405 : : * switch to IMPLICIT_INPROGRESS state, creating an implicit transaction
4406 : : * block.
4407 : : *
4408 : : * For caller convenience, we consider all other transaction states as
4409 : : * legal here; otherwise the caller would need its own state check, which
4410 : : * seems rather pointless.
4411 : : */
4412 [ + + ]: 49281 : if (s->blockState == TBLOCK_STARTED)
4413 : 6192 : s->blockState = TBLOCK_IMPLICIT_INPROGRESS;
4414 : 49281 : }
4415 : :
4416 : : /*
4417 : : * EndImplicitTransactionBlock
4418 : : * End an implicit transaction block, if we're in one.
4419 : : *
4420 : : * Like EndTransactionBlock, we just make any needed blockState change here.
4421 : : * The real work will be done in the upcoming CommitTransactionCommand().
4422 : : */
4423 : : void
4424 : 19734 : EndImplicitTransactionBlock(void)
4425 : : {
4426 : 19734 : TransactionState s = CurrentTransactionState;
4427 : :
4428 : : /*
4429 : : * If we are in IMPLICIT_INPROGRESS state, switch back to STARTED state,
4430 : : * allowing CommitTransactionCommand to commit whatever happened during
4431 : : * the implicit transaction block as though it were a single statement.
4432 : : *
4433 : : * For caller convenience, we consider all other transaction states as
4434 : : * legal here; otherwise the caller would need its own state check, which
4435 : : * seems rather pointless.
4436 : : */
4437 [ + + ]: 19734 : if (s->blockState == TBLOCK_IMPLICIT_INPROGRESS)
4438 : 5570 : s->blockState = TBLOCK_STARTED;
4439 : 19734 : }
4440 : :
4441 : : /*
4442 : : * DefineSavepoint
4443 : : * This executes a SAVEPOINT command.
4444 : : */
4445 : : void
4446 : 1686 : DefineSavepoint(const char *name)
4447 : : {
4448 : 1686 : TransactionState s = CurrentTransactionState;
4449 : :
4450 : : /*
4451 : : * Workers synchronize transaction state at the beginning of each parallel
4452 : : * operation, so we can't account for new subtransactions after that
4453 : : * point. (Note that this check will certainly error out if s->blockState
4454 : : * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
4455 : : * below.)
4456 : : */
4457 [ + - - + ]: 1686 : if (IsInParallelMode() || IsParallelWorker())
4458 [ # # ]: 0 : ereport(ERROR,
4459 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4460 : : errmsg("cannot define savepoints during a parallel operation")));
4461 : :
4462 [ + + - - ]: 1686 : switch (s->blockState)
4463 : : {
4464 : 1678 : case TBLOCK_INPROGRESS:
4465 : : case TBLOCK_SUBINPROGRESS:
4466 : : /* Normal subtransaction start */
4467 : 1678 : PushTransaction();
4468 : 1678 : s = CurrentTransactionState; /* changed by push */
4469 : :
4470 : : /*
4471 : : * Savepoint names, like the TransactionState block itself, live
4472 : : * in TopTransactionContext.
4473 : : */
4474 [ + + ]: 1678 : if (name)
4475 : 1176 : s->name = MemoryContextStrdup(TopTransactionContext, name);
4476 : 1678 : break;
4477 : :
4478 : : /*
4479 : : * We disallow savepoint commands in implicit transaction blocks.
4480 : : * There would be no great difficulty in allowing them so far as
4481 : : * this module is concerned, but a savepoint seems inconsistent
4482 : : * with exec_simple_query's behavior of abandoning the whole query
4483 : : * string upon error. Also, the point of an implicit transaction
4484 : : * block (as opposed to a regular one) is to automatically close
4485 : : * after an error, so it's hard to see how a savepoint would fit
4486 : : * into that.
4487 : : *
4488 : : * The error messages for this are phrased as if there were no
4489 : : * active transaction block at all, which is historical but
4490 : : * perhaps could be improved.
4491 : : */
4492 : 8 : case TBLOCK_IMPLICIT_INPROGRESS:
4493 [ + - ]: 8 : ereport(ERROR,
4494 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4495 : : /* translator: %s represents an SQL statement name */
4496 : : errmsg("%s can only be used in transaction blocks",
4497 : : "SAVEPOINT")));
4498 : : break;
4499 : :
4500 : : /* These cases are invalid. */
4501 : 0 : case TBLOCK_DEFAULT:
4502 : : case TBLOCK_STARTED:
4503 : : case TBLOCK_BEGIN:
4504 : : case TBLOCK_PARALLEL_INPROGRESS:
4505 : : case TBLOCK_SUBBEGIN:
4506 : : case TBLOCK_END:
4507 : : case TBLOCK_SUBRELEASE:
4508 : : case TBLOCK_SUBCOMMIT:
4509 : : case TBLOCK_ABORT:
4510 : : case TBLOCK_SUBABORT:
4511 : : case TBLOCK_ABORT_END:
4512 : : case TBLOCK_SUBABORT_END:
4513 : : case TBLOCK_ABORT_PENDING:
4514 : : case TBLOCK_SUBABORT_PENDING:
4515 : : case TBLOCK_SUBRESTART:
4516 : : case TBLOCK_SUBABORT_RESTART:
4517 : : case TBLOCK_PREPARE:
4518 [ # # ]: 0 : elog(FATAL, "DefineSavepoint: unexpected state %s",
4519 : : BlockStateAsString(s->blockState));
4520 : : break;
4521 : : }
4522 : 1678 : }
4523 : :
4524 : : /*
4525 : : * ReleaseSavepoint
4526 : : * This executes a RELEASE command.
4527 : : *
4528 : : * As above, we don't actually do anything here except change blockState.
4529 : : */
4530 : : void
4531 : 185 : ReleaseSavepoint(const char *name)
4532 : : {
4533 : 185 : TransactionState s = CurrentTransactionState;
4534 : : TransactionState target,
4535 : : xact;
4536 : :
4537 : : /*
4538 : : * Workers synchronize transaction state at the beginning of each parallel
4539 : : * operation, so we can't account for transaction state change after that
4540 : : * point. (Note that this check will certainly error out if s->blockState
4541 : : * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
4542 : : * below.)
4543 : : */
4544 [ + - - + ]: 185 : if (IsInParallelMode() || IsParallelWorker())
4545 [ # # ]: 0 : ereport(ERROR,
4546 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4547 : : errmsg("cannot release savepoints during a parallel operation")));
4548 : :
4549 [ - + + - : 185 : switch (s->blockState)
- ]
4550 : : {
4551 : : /*
4552 : : * We can't release a savepoint if there is no savepoint defined.
4553 : : */
4554 : 0 : case TBLOCK_INPROGRESS:
4555 [ # # ]: 0 : ereport(ERROR,
4556 : : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4557 : : errmsg("savepoint \"%s\" does not exist", name)));
4558 : : break;
4559 : :
4560 : 4 : case TBLOCK_IMPLICIT_INPROGRESS:
4561 : : /* See comment about implicit transactions in DefineSavepoint */
4562 [ + - ]: 4 : ereport(ERROR,
4563 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4564 : : /* translator: %s represents an SQL statement name */
4565 : : errmsg("%s can only be used in transaction blocks",
4566 : : "RELEASE SAVEPOINT")));
4567 : : break;
4568 : :
4569 : : /*
4570 : : * We are in a non-aborted subtransaction. This is the only valid
4571 : : * case.
4572 : : */
4573 : 181 : case TBLOCK_SUBINPROGRESS:
4574 : 181 : break;
4575 : :
4576 : : /* These cases are invalid. */
4577 : 0 : case TBLOCK_DEFAULT:
4578 : : case TBLOCK_STARTED:
4579 : : case TBLOCK_BEGIN:
4580 : : case TBLOCK_PARALLEL_INPROGRESS:
4581 : : case TBLOCK_SUBBEGIN:
4582 : : case TBLOCK_END:
4583 : : case TBLOCK_SUBRELEASE:
4584 : : case TBLOCK_SUBCOMMIT:
4585 : : case TBLOCK_ABORT:
4586 : : case TBLOCK_SUBABORT:
4587 : : case TBLOCK_ABORT_END:
4588 : : case TBLOCK_SUBABORT_END:
4589 : : case TBLOCK_ABORT_PENDING:
4590 : : case TBLOCK_SUBABORT_PENDING:
4591 : : case TBLOCK_SUBRESTART:
4592 : : case TBLOCK_SUBABORT_RESTART:
4593 : : case TBLOCK_PREPARE:
4594 [ # # ]: 0 : elog(FATAL, "ReleaseSavepoint: unexpected state %s",
4595 : : BlockStateAsString(s->blockState));
4596 : : break;
4597 : : }
4598 : :
4599 [ + - ]: 268 : for (target = s; target; target = target->parent)
4600 : : {
4601 [ + - + + ]: 268 : if (target->name && strcmp(target->name, name) == 0)
4602 : 181 : break;
4603 : : }
4604 : :
4605 [ - + ]: 181 : if (!target)
4606 [ # # ]: 0 : ereport(ERROR,
4607 : : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4608 : : errmsg("savepoint \"%s\" does not exist", name)));
4609 : :
4610 : : /* disallow crossing savepoint level boundaries */
4611 [ - + ]: 181 : if (target->savepointLevel != s->savepointLevel)
4612 [ # # ]: 0 : ereport(ERROR,
4613 : : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4614 : : errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
4615 : :
4616 : : /*
4617 : : * Mark "commit pending" all subtransactions up to the target
4618 : : * subtransaction. The actual commits will happen when control gets to
4619 : : * CommitTransactionCommand.
4620 : : */
4621 : 181 : xact = CurrentTransactionState;
4622 : : for (;;)
4623 : : {
4624 : 87 : Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
4625 : 268 : xact->blockState = TBLOCK_SUBRELEASE;
4626 [ + + ]: 268 : if (xact == target)
4627 : 181 : break;
4628 : 87 : xact = xact->parent;
4629 : : Assert(xact);
4630 : : }
4631 : 181 : }
4632 : :
4633 : : /*
4634 : : * RollbackToSavepoint
4635 : : * This executes a ROLLBACK TO <savepoint> command.
4636 : : *
4637 : : * As above, we don't actually do anything here except change blockState.
4638 : : */
4639 : : void
4640 : 510 : RollbackToSavepoint(const char *name)
4641 : : {
4642 : 510 : TransactionState s = CurrentTransactionState;
4643 : : TransactionState target,
4644 : : xact;
4645 : :
4646 : : /*
4647 : : * Workers synchronize transaction state at the beginning of each parallel
4648 : : * operation, so we can't account for transaction state change after that
4649 : : * point. (Note that this check will certainly error out if s->blockState
4650 : : * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
4651 : : * below.)
4652 : : */
4653 [ + - - + ]: 510 : if (IsInParallelMode() || IsParallelWorker())
4654 [ # # ]: 0 : ereport(ERROR,
4655 : : (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
4656 : : errmsg("cannot rollback to savepoints during a parallel operation")));
4657 : :
4658 [ + + + - : 510 : switch (s->blockState)
- ]
4659 : : {
4660 : : /*
4661 : : * We can't rollback to a savepoint if there is no savepoint
4662 : : * defined.
4663 : : */
4664 : 4 : case TBLOCK_INPROGRESS:
4665 : : case TBLOCK_ABORT:
4666 [ + - ]: 4 : ereport(ERROR,
4667 : : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4668 : : errmsg("savepoint \"%s\" does not exist", name)));
4669 : : break;
4670 : :
4671 : 4 : case TBLOCK_IMPLICIT_INPROGRESS:
4672 : : /* See comment about implicit transactions in DefineSavepoint */
4673 [ + - ]: 4 : ereport(ERROR,
4674 : : (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
4675 : : /* translator: %s represents an SQL statement name */
4676 : : errmsg("%s can only be used in transaction blocks",
4677 : : "ROLLBACK TO SAVEPOINT")));
4678 : : break;
4679 : :
4680 : : /*
4681 : : * There is at least one savepoint, so proceed.
4682 : : */
4683 : 502 : case TBLOCK_SUBINPROGRESS:
4684 : : case TBLOCK_SUBABORT:
4685 : 502 : break;
4686 : :
4687 : : /* These cases are invalid. */
4688 : 0 : case TBLOCK_DEFAULT:
4689 : : case TBLOCK_STARTED:
4690 : : case TBLOCK_BEGIN:
4691 : : case TBLOCK_PARALLEL_INPROGRESS:
4692 : : case TBLOCK_SUBBEGIN:
4693 : : case TBLOCK_END:
4694 : : case TBLOCK_SUBRELEASE:
4695 : : case TBLOCK_SUBCOMMIT:
4696 : : case TBLOCK_ABORT_END:
4697 : : case TBLOCK_SUBABORT_END:
4698 : : case TBLOCK_ABORT_PENDING:
4699 : : case TBLOCK_SUBABORT_PENDING:
4700 : : case TBLOCK_SUBRESTART:
4701 : : case TBLOCK_SUBABORT_RESTART:
4702 : : case TBLOCK_PREPARE:
4703 [ # # ]: 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4704 : : BlockStateAsString(s->blockState));
4705 : : break;
4706 : : }
4707 : :
4708 [ + - ]: 540 : for (target = s; target; target = target->parent)
4709 : : {
4710 [ + - + + ]: 540 : if (target->name && strcmp(target->name, name) == 0)
4711 : 502 : break;
4712 : : }
4713 : :
4714 [ - + ]: 502 : if (!target)
4715 [ # # ]: 0 : ereport(ERROR,
4716 : : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4717 : : errmsg("savepoint \"%s\" does not exist", name)));
4718 : :
4719 : : /* disallow crossing savepoint level boundaries */
4720 [ - + ]: 502 : if (target->savepointLevel != s->savepointLevel)
4721 [ # # ]: 0 : ereport(ERROR,
4722 : : (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
4723 : : errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
4724 : :
4725 : : /*
4726 : : * Mark "abort pending" all subtransactions up to the target
4727 : : * subtransaction. The actual aborts will happen when control gets to
4728 : : * CommitTransactionCommand.
4729 : : */
4730 : 502 : xact = CurrentTransactionState;
4731 : : for (;;)
4732 : : {
4733 [ + + ]: 540 : if (xact == target)
4734 : 502 : break;
4735 [ + - ]: 38 : if (xact->blockState == TBLOCK_SUBINPROGRESS)
4736 : 38 : xact->blockState = TBLOCK_SUBABORT_PENDING;
4737 [ # # ]: 0 : else if (xact->blockState == TBLOCK_SUBABORT)
4738 : 0 : xact->blockState = TBLOCK_SUBABORT_END;
4739 : : else
4740 [ # # ]: 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4741 : : BlockStateAsString(xact->blockState));
4742 : 38 : xact = xact->parent;
4743 : : Assert(xact);
4744 : : }
4745 : :
4746 : : /* And mark the target as "restart pending" */
4747 [ + + ]: 502 : if (xact->blockState == TBLOCK_SUBINPROGRESS)
4748 : 333 : xact->blockState = TBLOCK_SUBRESTART;
4749 [ + - ]: 169 : else if (xact->blockState == TBLOCK_SUBABORT)
4750 : 169 : xact->blockState = TBLOCK_SUBABORT_RESTART;
4751 : : else
4752 [ # # ]: 0 : elog(FATAL, "RollbackToSavepoint: unexpected state %s",
4753 : : BlockStateAsString(xact->blockState));
4754 : 502 : }
4755 : :
4756 : : /*
4757 : : * BeginInternalSubTransaction
4758 : : * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
4759 : : * TBLOCK_IMPLICIT_INPROGRESS, TBLOCK_PARALLEL_INPROGRESS, TBLOCK_END,
4760 : : * and TBLOCK_PREPARE states, and therefore it can safely be used in
4761 : : * functions that might be called when not inside a BEGIN block or when
4762 : : * running deferred triggers at COMMIT/PREPARE time. Also, it
4763 : : * automatically does CommitTransactionCommand/StartTransactionCommand
4764 : : * instead of expecting the caller to do it.
4765 : : */
4766 : : void
4767 : 21179 : BeginInternalSubTransaction(const char *name)
4768 : : {
4769 : 21179 : TransactionState s = CurrentTransactionState;
4770 : 21179 : bool save_ExitOnAnyError = ExitOnAnyError;
4771 : :
4772 : : /*
4773 : : * Errors within this function are improbable, but if one does happen we
4774 : : * force a FATAL exit. Callers generally aren't prepared to handle losing
4775 : : * control, and moreover our transaction state is probably corrupted if we
4776 : : * fail partway through; so an ordinary ERROR longjmp isn't okay.
4777 : : */
4778 : 21179 : ExitOnAnyError = true;
4779 : :
4780 : : /*
4781 : : * We do not check for parallel mode here. It's permissible to start and
4782 : : * end "internal" subtransactions while in parallel mode, so long as no
4783 : : * new XIDs or command IDs are assigned. Enforcement of that occurs in
4784 : : * AssignTransactionId() and CommandCounterIncrement().
4785 : : */
4786 : :
4787 [ + - - ]: 21179 : switch (s->blockState)
4788 : : {
4789 : 21179 : case TBLOCK_STARTED:
4790 : : case TBLOCK_INPROGRESS:
4791 : : case TBLOCK_IMPLICIT_INPROGRESS:
4792 : : case TBLOCK_PARALLEL_INPROGRESS:
4793 : : case TBLOCK_END:
4794 : : case TBLOCK_PREPARE:
4795 : : case TBLOCK_SUBINPROGRESS:
4796 : : /* Normal subtransaction start */
4797 : 21179 : PushTransaction();
4798 : 21179 : s = CurrentTransactionState; /* changed by push */
4799 : :
4800 : : /*
4801 : : * Savepoint names, like the TransactionState block itself, live
4802 : : * in TopTransactionContext.
4803 : : */
4804 [ + + ]: 21179 : if (name)
4805 : 1021 : s->name = MemoryContextStrdup(TopTransactionContext, name);
4806 : 21179 : break;
4807 : :
4808 : : /* These cases are invalid. */
4809 : 0 : case TBLOCK_DEFAULT:
4810 : : case TBLOCK_BEGIN:
4811 : : case TBLOCK_SUBBEGIN:
4812 : : case TBLOCK_SUBRELEASE:
4813 : : case TBLOCK_SUBCOMMIT:
4814 : : case TBLOCK_ABORT:
4815 : : case TBLOCK_SUBABORT:
4816 : : case TBLOCK_ABORT_END:
4817 : : case TBLOCK_SUBABORT_END:
4818 : : case TBLOCK_ABORT_PENDING:
4819 : : case TBLOCK_SUBABORT_PENDING:
4820 : : case TBLOCK_SUBRESTART:
4821 : : case TBLOCK_SUBABORT_RESTART:
4822 [ # # ]: 0 : elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
4823 : : BlockStateAsString(s->blockState));
4824 : : break;
4825 : : }
4826 : :
4827 : 21179 : CommitTransactionCommand();
4828 : 21179 : StartTransactionCommand();
4829 : :
4830 : 21179 : ExitOnAnyError = save_ExitOnAnyError;
4831 : 21179 : }
4832 : :
4833 : : /*
4834 : : * ReleaseCurrentSubTransaction
4835 : : *
4836 : : * RELEASE (ie, commit) the innermost subtransaction, regardless of its
4837 : : * savepoint name (if any).
4838 : : * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
4839 : : */
4840 : : void
4841 : 16518 : ReleaseCurrentSubTransaction(void)
4842 : : {
4843 : 16518 : TransactionState s = CurrentTransactionState;
4844 : :
4845 : : /*
4846 : : * We do not check for parallel mode here. It's permissible to start and
4847 : : * end "internal" subtransactions while in parallel mode, so long as no
4848 : : * new XIDs or command IDs are assigned.
4849 : : */
4850 : :
4851 [ - + ]: 16518 : if (s->blockState != TBLOCK_SUBINPROGRESS)
4852 [ # # ]: 0 : elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
4853 : : BlockStateAsString(s->blockState));
4854 : : Assert(s->state == TRANS_INPROGRESS);
4855 : 16518 : MemoryContextSwitchTo(CurTransactionContext);
4856 : 16518 : CommitSubTransaction();
4857 : 16518 : s = CurrentTransactionState; /* changed by pop */
4858 : : Assert(s->state == TRANS_INPROGRESS);
4859 : 16518 : }
4860 : :
4861 : : /*
4862 : : * RollbackAndReleaseCurrentSubTransaction
4863 : : *
4864 : : * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
4865 : : * of its savepoint name (if any).
4866 : : * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
4867 : : */
4868 : : void
4869 : 4661 : RollbackAndReleaseCurrentSubTransaction(void)
4870 : : {
4871 : 4661 : TransactionState s = CurrentTransactionState;
4872 : :
4873 : : /*
4874 : : * We do not check for parallel mode here. It's permissible to start and
4875 : : * end "internal" subtransactions while in parallel mode, so long as no
4876 : : * new XIDs or command IDs are assigned.
4877 : : */
4878 : :
4879 [ + - - ]: 4661 : switch (s->blockState)
4880 : : {
4881 : : /* Must be in a subtransaction */
4882 : 4661 : case TBLOCK_SUBINPROGRESS:
4883 : : case TBLOCK_SUBABORT:
4884 : 4661 : break;
4885 : :
4886 : : /* These cases are invalid. */
4887 : 0 : case TBLOCK_DEFAULT:
4888 : : case TBLOCK_STARTED:
4889 : : case TBLOCK_BEGIN:
4890 : : case TBLOCK_IMPLICIT_INPROGRESS:
4891 : : case TBLOCK_PARALLEL_INPROGRESS:
4892 : : case TBLOCK_SUBBEGIN:
4893 : : case TBLOCK_INPROGRESS:
4894 : : case TBLOCK_END:
4895 : : case TBLOCK_SUBRELEASE:
4896 : : case TBLOCK_SUBCOMMIT:
4897 : : case TBLOCK_ABORT:
4898 : : case TBLOCK_ABORT_END:
4899 : : case TBLOCK_SUBABORT_END:
4900 : : case TBLOCK_ABORT_PENDING:
4901 : : case TBLOCK_SUBABORT_PENDING:
4902 : : case TBLOCK_SUBRESTART:
4903 : : case TBLOCK_SUBABORT_RESTART:
4904 : : case TBLOCK_PREPARE:
4905 [ # # ]: 0 : elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
4906 : : BlockStateAsString(s->blockState));
4907 : : break;
4908 : : }
4909 : :
4910 : : /*
4911 : : * Abort the current subtransaction, if needed.
4912 : : */
4913 [ + + ]: 4661 : if (s->blockState == TBLOCK_SUBINPROGRESS)
4914 : 3640 : AbortSubTransaction();
4915 : :
4916 : : /* And clean it up, too */
4917 : 4661 : CleanupSubTransaction();
4918 : :
4919 : 4661 : s = CurrentTransactionState; /* changed by pop */
4920 : : Assert(s->blockState == TBLOCK_SUBINPROGRESS ||
4921 : : s->blockState == TBLOCK_INPROGRESS ||
4922 : : s->blockState == TBLOCK_IMPLICIT_INPROGRESS ||
4923 : : s->blockState == TBLOCK_PARALLEL_INPROGRESS ||
4924 : : s->blockState == TBLOCK_END ||
4925 : : s->blockState == TBLOCK_PREPARE ||
4926 : : s->blockState == TBLOCK_STARTED);
4927 : 4661 : }
4928 : :
4929 : : /*
4930 : : * AbortOutOfAnyTransaction
4931 : : *
4932 : : * This routine is provided for error recovery purposes. It aborts any
4933 : : * active transaction or transaction block, leaving the system in a known
4934 : : * idle state.
4935 : : */
4936 : : void
4937 : 21687 : AbortOutOfAnyTransaction(void)
4938 : : {
4939 : 21687 : TransactionState s = CurrentTransactionState;
4940 : :
4941 : : /* Ensure we're not running in a doomed memory context */
4942 : 21687 : AtAbort_Memory();
4943 : :
4944 : : /*
4945 : : * Get out of any transaction or nested transaction
4946 : : */
4947 : : do
4948 : : {
4949 [ + + + + : 21689 : switch (s->blockState)
- - ]
4950 : : {
4951 : 20973 : case TBLOCK_DEFAULT:
4952 [ - + ]: 20973 : if (s->state == TRANS_DEFAULT)
4953 : : {
4954 : : /* Not in a transaction, do nothing */
4955 : : }
4956 : : else
4957 : : {
4958 : : /*
4959 : : * We can get here after an error during transaction start
4960 : : * (state will be TRANS_START). Need to clean up the
4961 : : * incompletely started transaction. First, adjust the
4962 : : * low-level state to suppress warning message from
4963 : : * AbortTransaction.
4964 : : */
4965 [ # # ]: 0 : if (s->state == TRANS_START)
4966 : 0 : s->state = TRANS_INPROGRESS;
4967 : 0 : AbortTransaction();
4968 : 0 : CleanupTransaction();
4969 : : }
4970 : 20973 : break;
4971 : 697 : case TBLOCK_STARTED:
4972 : : case TBLOCK_BEGIN:
4973 : : case TBLOCK_INPROGRESS:
4974 : : case TBLOCK_IMPLICIT_INPROGRESS:
4975 : : case TBLOCK_PARALLEL_INPROGRESS:
4976 : : case TBLOCK_END:
4977 : : case TBLOCK_ABORT_PENDING:
4978 : : case TBLOCK_PREPARE:
4979 : : /* In a transaction, so clean up */
4980 : 697 : AbortTransaction();
4981 : 697 : CleanupTransaction();
4982 : 697 : s->blockState = TBLOCK_DEFAULT;
4983 : 697 : break;
4984 : 17 : case TBLOCK_ABORT:
4985 : : case TBLOCK_ABORT_END:
4986 : :
4987 : : /*
4988 : : * AbortTransaction is already done, still need Cleanup.
4989 : : * However, if we failed partway through running ROLLBACK,
4990 : : * there will be an active portal running that command, which
4991 : : * we need to shut down before doing CleanupTransaction.
4992 : : */
4993 : 17 : AtAbort_Portals();
4994 : 17 : CleanupTransaction();
4995 : 17 : s->blockState = TBLOCK_DEFAULT;
4996 : 17 : break;
4997 : :
4998 : : /*
4999 : : * In a subtransaction, so clean it up and abort parent too
5000 : : */
5001 : 2 : case TBLOCK_SUBBEGIN:
5002 : : case TBLOCK_SUBINPROGRESS:
5003 : : case TBLOCK_SUBRELEASE:
5004 : : case TBLOCK_SUBCOMMIT:
5005 : : case TBLOCK_SUBABORT_PENDING:
5006 : : case TBLOCK_SUBRESTART:
5007 : 2 : AbortSubTransaction();
5008 : 2 : CleanupSubTransaction();
5009 : 2 : s = CurrentTransactionState; /* changed by pop */
5010 : 2 : break;
5011 : :
5012 : 0 : case TBLOCK_SUBABORT:
5013 : : case TBLOCK_SUBABORT_END:
5014 : : case TBLOCK_SUBABORT_RESTART:
5015 : : /* As above, but AbortSubTransaction already done */
5016 [ # # ]: 0 : if (s->curTransactionOwner)
5017 : : {
5018 : : /* As in TBLOCK_ABORT, might have a live portal to zap */
5019 : 0 : AtSubAbort_Portals(s->subTransactionId,
5020 : 0 : s->parent->subTransactionId,
5021 : : s->curTransactionOwner,
5022 : 0 : s->parent->curTransactionOwner);
5023 : : }
5024 : 0 : CleanupSubTransaction();
5025 : 0 : s = CurrentTransactionState; /* changed by pop */
5026 : 0 : break;
5027 : : }
5028 [ + + ]: 21689 : } while (s->blockState != TBLOCK_DEFAULT);
5029 : :
5030 : : /* Should be out of all subxacts now */
5031 : : Assert(s->parent == NULL);
5032 : :
5033 : : /*
5034 : : * Revert to TopMemoryContext, to ensure we exit in a well-defined state
5035 : : * whether there were any transactions to close or not. (Callers that
5036 : : * don't intend to exit soon should switch to some other context to avoid
5037 : : * long-term memory leaks.)
5038 : : */
5039 : 21687 : MemoryContextSwitchTo(TopMemoryContext);
5040 : 21687 : }
5041 : :
5042 : : /*
5043 : : * IsTransactionBlock --- are we within a transaction block?
5044 : : */
5045 : : bool
5046 : 351330 : IsTransactionBlock(void)
5047 : : {
5048 : 351330 : TransactionState s = CurrentTransactionState;
5049 : :
5050 [ + + + + ]: 351330 : if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
5051 : 281624 : return false;
5052 : :
5053 : 69706 : return true;
5054 : : }
5055 : :
5056 : : /*
5057 : : * IsTransactionOrTransactionBlock --- are we within either a transaction
5058 : : * or a transaction block? (The backend is only really "idle" when this
5059 : : * returns false.)
5060 : : *
5061 : : * This should match up with IsTransactionBlock and IsTransactionState.
5062 : : */
5063 : : bool
5064 : 462678 : IsTransactionOrTransactionBlock(void)
5065 : : {
5066 : 462678 : TransactionState s = CurrentTransactionState;
5067 : :
5068 [ + + ]: 462678 : if (s->blockState == TBLOCK_DEFAULT)
5069 : 368155 : return false;
5070 : :
5071 : 94523 : return true;
5072 : : }
5073 : :
5074 : : /*
5075 : : * TransactionBlockStatusCode - return status code to send in ReadyForQuery
5076 : : */
5077 : : char
5078 : 420188 : TransactionBlockStatusCode(void)
5079 : : {
5080 : 420188 : TransactionState s = CurrentTransactionState;
5081 : :
5082 [ + + + - ]: 420188 : switch (s->blockState)
5083 : : {
5084 : 326412 : case TBLOCK_DEFAULT:
5085 : : case TBLOCK_STARTED:
5086 : 326412 : return 'I'; /* idle --- not in transaction */
5087 : 92573 : case TBLOCK_BEGIN:
5088 : : case TBLOCK_SUBBEGIN:
5089 : : case TBLOCK_INPROGRESS:
5090 : : case TBLOCK_IMPLICIT_INPROGRESS:
5091 : : case TBLOCK_PARALLEL_INPROGRESS:
5092 : : case TBLOCK_SUBINPROGRESS:
5093 : : case TBLOCK_END:
5094 : : case TBLOCK_SUBRELEASE:
5095 : : case TBLOCK_SUBCOMMIT:
5096 : : case TBLOCK_PREPARE:
5097 : 92573 : return 'T'; /* in transaction */
5098 : 1203 : case TBLOCK_ABORT:
5099 : : case TBLOCK_SUBABORT:
5100 : : case TBLOCK_ABORT_END:
5101 : : case TBLOCK_SUBABORT_END:
5102 : : case TBLOCK_ABORT_PENDING:
5103 : : case TBLOCK_SUBABORT_PENDING:
5104 : : case TBLOCK_SUBRESTART:
5105 : : case TBLOCK_SUBABORT_RESTART:
5106 : 1203 : return 'E'; /* in failed transaction */
5107 : : }
5108 : :
5109 : : /* should never get here */
5110 [ # # ]: 0 : elog(FATAL, "invalid transaction block state: %s",
5111 : : BlockStateAsString(s->blockState));
5112 : : return 0; /* keep compiler quiet */
5113 : : }
5114 : :
5115 : : /*
5116 : : * IsSubTransaction
5117 : : */
5118 : : bool
5119 : 731081 : IsSubTransaction(void)
5120 : : {
5121 : 731081 : TransactionState s = CurrentTransactionState;
5122 : :
5123 [ + + ]: 731081 : if (s->nestingLevel >= 2)
5124 : 251 : return true;
5125 : :
5126 : 730830 : return false;
5127 : : }
5128 : :
5129 : : /*
5130 : : * StartSubTransaction
5131 : : *
5132 : : * If you're wondering why this is separate from PushTransaction: it's because
5133 : : * we can't conveniently do this stuff right inside DefineSavepoint. The
5134 : : * SAVEPOINT utility command will be executed inside a Portal, and if we
5135 : : * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
5136 : : * the Portal will undo those settings. So we make DefineSavepoint just
5137 : : * push a dummy transaction block, and when control returns to the main
5138 : : * idle loop, CommitTransactionCommand will be called, and we'll come here
5139 : : * to finish starting the subtransaction.
5140 : : */
5141 : : static void
5142 : 22857 : StartSubTransaction(void)
5143 : : {
5144 : 22857 : TransactionState s = CurrentTransactionState;
5145 : :
5146 [ - + ]: 22857 : if (s->state != TRANS_DEFAULT)
5147 [ # # ]: 0 : elog(WARNING, "StartSubTransaction while in %s state",
5148 : : TransStateAsString(s->state));
5149 : :
5150 : 22857 : s->state = TRANS_START;
5151 : :
5152 : : /*
5153 : : * Initialize subsystems for new subtransaction
5154 : : *
5155 : : * must initialize resource-management stuff first
5156 : : */
5157 : 22857 : AtSubStart_Memory();
5158 : 22857 : AtSubStart_ResourceOwner();
5159 : 22857 : AfterTriggerBeginSubXact();
5160 : :
5161 : 22857 : s->state = TRANS_INPROGRESS;
5162 : :
5163 : : /*
5164 : : * Call start-of-subxact callbacks
5165 : : */
5166 : 22857 : CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
5167 : 22857 : s->parent->subTransactionId);
5168 : :
5169 : 22857 : ShowTransactionState("StartSubTransaction");
5170 : 22857 : }
5171 : :
5172 : : /*
5173 : : * CommitSubTransaction
5174 : : *
5175 : : * The caller has to make sure to always reassign CurrentTransactionState
5176 : : * if it has a local pointer to it after calling this function.
5177 : : */
5178 : : static void
5179 : 17377 : CommitSubTransaction(void)
5180 : : {
5181 : 17377 : TransactionState s = CurrentTransactionState;
5182 : :
5183 : 17377 : ShowTransactionState("CommitSubTransaction");
5184 : :
5185 [ - + ]: 17377 : if (s->state != TRANS_INPROGRESS)
5186 [ # # ]: 0 : elog(WARNING, "CommitSubTransaction while in %s state",
5187 : : TransStateAsString(s->state));
5188 : :
5189 : : /* Pre-commit processing goes here */
5190 : :
5191 : 17377 : CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId,
5192 : 17377 : s->parent->subTransactionId);
5193 : :
5194 : : /*
5195 : : * If this subxact has started any unfinished parallel operation, clean up
5196 : : * its workers and exit parallel mode. Warn about leaked resources.
5197 : : */
5198 : 17377 : AtEOSubXact_Parallel(true, s->subTransactionId);
5199 [ - + ]: 17377 : if (s->parallelModeLevel != 0)
5200 : : {
5201 [ # # ]: 0 : elog(WARNING, "parallelModeLevel is %d not 0 at end of subtransaction",
5202 : : s->parallelModeLevel);
5203 : 0 : s->parallelModeLevel = 0;
5204 : : }
5205 : :
5206 : : /* Do the actual "commit", such as it is */
5207 : 17377 : s->state = TRANS_COMMIT;
5208 : :
5209 : : /* Must CCI to ensure commands of subtransaction are seen as done */
5210 : 17377 : CommandCounterIncrement();
5211 : :
5212 : : /*
5213 : : * Prior to 8.4 we marked subcommit in clog at this point. We now only
5214 : : * perform that step, if required, as part of the atomic update of the
5215 : : * whole transaction tree at top level commit or abort.
5216 : : */
5217 : :
5218 : : /* Post-commit cleanup */
5219 [ + + ]: 17377 : if (FullTransactionIdIsValid(s->fullTransactionId))
5220 : 15466 : AtSubCommit_childXids();
5221 : 17377 : AfterTriggerEndSubXact(true);
5222 : 17377 : AtSubCommit_Portals(s->subTransactionId,
5223 : 17377 : s->parent->subTransactionId,
5224 : 17377 : s->parent->nestingLevel,
5225 : 17377 : s->parent->curTransactionOwner);
5226 : 17377 : AtEOSubXact_LargeObject(true, s->subTransactionId,
5227 : 17377 : s->parent->subTransactionId);
5228 : 17377 : AtSubCommit_Notify();
5229 : :
5230 : 17377 : CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
5231 : 17377 : s->parent->subTransactionId);
5232 : :
5233 : 17377 : ResourceOwnerRelease(s->curTransactionOwner,
5234 : : RESOURCE_RELEASE_BEFORE_LOCKS,
5235 : : true, false);
5236 : 17377 : AtEOSubXact_RelationCache(true, s->subTransactionId,
5237 : 17377 : s->parent->subTransactionId);
5238 : 17377 : AtEOSubXact_TypeCache();
5239 : 17377 : AtEOSubXact_Inval(true);
5240 : 17377 : AtSubCommit_smgr();
5241 : :
5242 : : /*
5243 : : * The only lock we actually release here is the subtransaction XID lock.
5244 : : */
5245 : 17377 : CurrentResourceOwner = s->curTransactionOwner;
5246 [ + + ]: 17377 : if (FullTransactionIdIsValid(s->fullTransactionId))
5247 : 15466 : XactLockTableDelete(XidFromFullTransactionId(s->fullTransactionId));
5248 : :
5249 : : /*
5250 : : * Other locks should get transferred to their parent resource owner.
5251 : : */
5252 : 17377 : ResourceOwnerRelease(s->curTransactionOwner,
5253 : : RESOURCE_RELEASE_LOCKS,
5254 : : true, false);
5255 : 17377 : ResourceOwnerRelease(s->curTransactionOwner,
5256 : : RESOURCE_RELEASE_AFTER_LOCKS,
5257 : : true, false);
5258 : :
5259 : 17377 : AtEOXact_GUC(true, s->gucNestLevel);
5260 : 17377 : AtEOSubXact_SPI(true, s->subTransactionId);
5261 : 17377 : AtEOSubXact_on_commit_actions(true, s->subTransactionId,
5262 : 17377 : s->parent->subTransactionId);
5263 : 17377 : AtEOSubXact_Namespace(true, s->subTransactionId,
5264 : 17377 : s->parent->subTransactionId);
5265 : 17377 : AtEOSubXact_Files(true, s->subTransactionId,
5266 : 17377 : s->parent->subTransactionId);
5267 : 17377 : AtEOSubXact_HashTables(true, s->nestingLevel);
5268 : 17377 : AtEOSubXact_PgStat(true, s->nestingLevel);
5269 : 17377 : AtSubCommit_Snapshot(s->nestingLevel);
5270 : :
5271 : : /*
5272 : : * We need to restore the upper transaction's read-only state, in case the
5273 : : * upper is read-write while the child is read-only; GUC will incorrectly
5274 : : * think it should leave the child state in place.
5275 : : */
5276 : 17377 : XactReadOnly = s->prevXactReadOnly;
5277 : :
5278 : 17377 : CurrentResourceOwner = s->parent->curTransactionOwner;
5279 : 17377 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5280 : 17377 : ResourceOwnerDelete(s->curTransactionOwner);
5281 : 17377 : s->curTransactionOwner = NULL;
5282 : :
5283 : 17377 : AtSubCommit_Memory();
5284 : :
5285 : 17377 : s->state = TRANS_DEFAULT;
5286 : :
5287 : 17377 : PopTransaction();
5288 : 17377 : }
5289 : :
5290 : : /*
5291 : : * AbortSubTransaction
5292 : : */
5293 : : static void
5294 : 5480 : AbortSubTransaction(void)
5295 : : {
5296 : 5480 : TransactionState s = CurrentTransactionState;
5297 : :
5298 : : /* Prevent cancel/die interrupt while cleaning up */
5299 : 5480 : HOLD_INTERRUPTS();
5300 : :
5301 : : /* Make sure we have a valid memory context and resource owner */
5302 : 5480 : AtSubAbort_Memory();
5303 : 5480 : AtSubAbort_ResourceOwner();
5304 : :
5305 : : /*
5306 : : * Release any LW locks we might be holding as quickly as possible.
5307 : : * (Regular locks, however, must be held till we finish aborting.)
5308 : : * Releasing LW locks is critical since we might try to grab them again
5309 : : * while cleaning up!
5310 : : *
5311 : : * FIXME This may be incorrect --- Are there some locks we should keep?
5312 : : * Buffer locks, for example? I don't think so but I'm not sure.
5313 : : */
5314 : 5480 : LWLockReleaseAll();
5315 : :
5316 : : /*
5317 : : * Cleanup waiting for LSN if any.
5318 : : */
5319 : 5480 : WaitLSNCleanup();
5320 : :
5321 : 5480 : pgstat_report_wait_end();
5322 : 5480 : pgstat_progress_end_command();
5323 : :
5324 : 5480 : pgaio_error_cleanup();
5325 : :
5326 : 5480 : UnlockBuffers();
5327 : :
5328 : : /* Reset WAL record construction state */
5329 : 5480 : XLogResetInsertion();
5330 : :
5331 : : /* Cancel condition variable sleep */
5332 : 5480 : ConditionVariableCancelSleep();
5333 : :
5334 : : /*
5335 : : * Also clean up any open wait for lock, since the lock manager will choke
5336 : : * if we try to wait for another lock before doing this.
5337 : : */
5338 : 5480 : LockErrorCleanup();
5339 : :
5340 : : /*
5341 : : * If any timeout events are still active, make sure the timeout interrupt
5342 : : * is scheduled. This covers possible loss of a timeout interrupt due to
5343 : : * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
5344 : : * We delay this till after LockErrorCleanup so that we don't uselessly
5345 : : * reschedule lock or deadlock check timeouts.
5346 : : */
5347 : 5480 : reschedule_timeouts();
5348 : :
5349 : : /*
5350 : : * Re-enable signals, in case we got here by longjmp'ing out of a signal
5351 : : * handler. We do this fairly early in the sequence so that the timeout
5352 : : * infrastructure will be functional if needed while aborting.
5353 : : */
5354 : 5480 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
5355 : :
5356 : : /*
5357 : : * check the current transaction state
5358 : : */
5359 : 5480 : ShowTransactionState("AbortSubTransaction");
5360 : :
5361 [ - + ]: 5480 : if (s->state != TRANS_INPROGRESS)
5362 [ # # ]: 0 : elog(WARNING, "AbortSubTransaction while in %s state",
5363 : : TransStateAsString(s->state));
5364 : :
5365 : 5480 : s->state = TRANS_ABORT;
5366 : :
5367 : : /*
5368 : : * Reset user ID which might have been changed transiently. (See notes in
5369 : : * AbortTransaction.)
5370 : : */
5371 : 5480 : SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
5372 : :
5373 : : /* Forget about any active REINDEX. */
5374 : 5480 : ResetReindexState(s->nestingLevel);
5375 : :
5376 : : /* Reset logical streaming state. */
5377 : 5480 : ResetLogicalStreamingState();
5378 : :
5379 : : /*
5380 : : * No need for SnapBuildResetExportedSnapshotState() here, snapshot
5381 : : * exports are not supported in subtransactions.
5382 : : */
5383 : :
5384 : : /*
5385 : : * If this subxact has started any unfinished parallel operation, clean up
5386 : : * its workers and exit parallel mode. Don't warn about leaked resources.
5387 : : */
5388 : 5480 : AtEOSubXact_Parallel(false, s->subTransactionId);
5389 : 5480 : s->parallelModeLevel = 0;
5390 : :
5391 : : /*
5392 : : * We can skip all this stuff if the subxact failed before creating a
5393 : : * ResourceOwner...
5394 : : */
5395 [ + - ]: 5480 : if (s->curTransactionOwner)
5396 : : {
5397 : 5480 : AfterTriggerEndSubXact(false);
5398 : 5480 : AtSubAbort_Portals(s->subTransactionId,
5399 : 5480 : s->parent->subTransactionId,
5400 : : s->curTransactionOwner,
5401 : 5480 : s->parent->curTransactionOwner);
5402 : 5480 : AtEOSubXact_LargeObject(false, s->subTransactionId,
5403 : 5480 : s->parent->subTransactionId);
5404 : 5480 : AtSubAbort_Notify();
5405 : :
5406 : : /* Advertise the fact that we aborted in pg_xact. */
5407 : 5480 : (void) RecordTransactionAbort(true);
5408 : :
5409 : : /* Post-abort cleanup */
5410 [ + + ]: 5480 : if (FullTransactionIdIsValid(s->fullTransactionId))
5411 : 889 : AtSubAbort_childXids();
5412 : :
5413 : 5480 : CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
5414 : 5480 : s->parent->subTransactionId);
5415 : :
5416 : 5480 : ResourceOwnerRelease(s->curTransactionOwner,
5417 : : RESOURCE_RELEASE_BEFORE_LOCKS,
5418 : : false, false);
5419 : :
5420 : 5480 : AtEOXact_Aio(false);
5421 : 5480 : AtEOSubXact_RelationCache(false, s->subTransactionId,
5422 : 5480 : s->parent->subTransactionId);
5423 : 5480 : AtEOSubXact_TypeCache();
5424 : 5480 : AtEOSubXact_Inval(false);
5425 : 5480 : ResourceOwnerRelease(s->curTransactionOwner,
5426 : : RESOURCE_RELEASE_LOCKS,
5427 : : false, false);
5428 : 5480 : ResourceOwnerRelease(s->curTransactionOwner,
5429 : : RESOURCE_RELEASE_AFTER_LOCKS,
5430 : : false, false);
5431 : 5480 : AtSubAbort_smgr();
5432 : :
5433 : 5480 : AtEOXact_GUC(false, s->gucNestLevel);
5434 : 5480 : AtEOSubXact_SPI(false, s->subTransactionId);
5435 : 5480 : AtEOSubXact_on_commit_actions(false, s->subTransactionId,
5436 : 5480 : s->parent->subTransactionId);
5437 : 5480 : AtEOSubXact_Namespace(false, s->subTransactionId,
5438 : 5480 : s->parent->subTransactionId);
5439 : 5480 : AtEOSubXact_Files(false, s->subTransactionId,
5440 : 5480 : s->parent->subTransactionId);
5441 : 5480 : AtEOSubXact_HashTables(false, s->nestingLevel);
5442 : 5480 : AtEOSubXact_PgStat(false, s->nestingLevel);
5443 : 5480 : AtSubAbort_Snapshot(s->nestingLevel);
5444 : : }
5445 : :
5446 : : /*
5447 : : * Restore the upper transaction's read-only state, too. This should be
5448 : : * redundant with GUC's cleanup but we may as well do it for consistency
5449 : : * with the commit case.
5450 : : */
5451 : 5480 : XactReadOnly = s->prevXactReadOnly;
5452 : :
5453 : 5480 : RESUME_INTERRUPTS();
5454 : 5480 : }
5455 : :
5456 : : /*
5457 : : * CleanupSubTransaction
5458 : : *
5459 : : * The caller has to make sure to always reassign CurrentTransactionState
5460 : : * if it has a local pointer to it after calling this function.
5461 : : */
5462 : : static void
5463 : 5480 : CleanupSubTransaction(void)
5464 : : {
5465 : 5480 : TransactionState s = CurrentTransactionState;
5466 : :
5467 : 5480 : ShowTransactionState("CleanupSubTransaction");
5468 : :
5469 [ - + ]: 5480 : if (s->state != TRANS_ABORT)
5470 [ # # ]: 0 : elog(WARNING, "CleanupSubTransaction while in %s state",
5471 : : TransStateAsString(s->state));
5472 : :
5473 : 5480 : AtSubCleanup_Portals(s->subTransactionId);
5474 : :
5475 : 5480 : CurrentResourceOwner = s->parent->curTransactionOwner;
5476 : 5480 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5477 [ + - ]: 5480 : if (s->curTransactionOwner)
5478 : 5480 : ResourceOwnerDelete(s->curTransactionOwner);
5479 : 5480 : s->curTransactionOwner = NULL;
5480 : :
5481 : 5480 : AtSubCleanup_Memory();
5482 : :
5483 : 5480 : s->state = TRANS_DEFAULT;
5484 : :
5485 : 5480 : PopTransaction();
5486 : 5480 : }
5487 : :
5488 : : /*
5489 : : * PushTransaction
5490 : : * Create transaction state stack entry for a subtransaction
5491 : : *
5492 : : * The caller has to make sure to always reassign CurrentTransactionState
5493 : : * if it has a local pointer to it after calling this function.
5494 : : */
5495 : : static void
5496 : 22857 : PushTransaction(void)
5497 : : {
5498 : 22857 : TransactionState p = CurrentTransactionState;
5499 : : TransactionState s;
5500 : :
5501 : : /*
5502 : : * We keep subtransaction state nodes in TopTransactionContext.
5503 : : */
5504 : : s = (TransactionState)
5505 : 22857 : MemoryContextAllocZero(TopTransactionContext,
5506 : : sizeof(TransactionStateData));
5507 : :
5508 : : /*
5509 : : * Assign a subtransaction ID, watching out for counter wraparound.
5510 : : */
5511 : 22857 : currentSubTransactionId += 1;
5512 [ - + ]: 22857 : if (currentSubTransactionId == InvalidSubTransactionId)
5513 : : {
5514 : 0 : currentSubTransactionId -= 1;
5515 : 0 : pfree(s);
5516 [ # # ]: 0 : ereport(ERROR,
5517 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5518 : : errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
5519 : : }
5520 : :
5521 : : /*
5522 : : * We can now stack a minimally valid subtransaction without fear of
5523 : : * failure.
5524 : : */
5525 : 22857 : s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
5526 : 22857 : s->subTransactionId = currentSubTransactionId;
5527 : 22857 : s->parent = p;
5528 : 22857 : s->nestingLevel = p->nestingLevel + 1;
5529 : 22857 : s->gucNestLevel = NewGUCNestLevel();
5530 : 22857 : s->savepointLevel = p->savepointLevel;
5531 : 22857 : s->state = TRANS_DEFAULT;
5532 : 22857 : s->blockState = TBLOCK_SUBBEGIN;
5533 : 22857 : GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
5534 : 22857 : s->prevXactReadOnly = XactReadOnly;
5535 : 22857 : s->startedInRecovery = p->startedInRecovery;
5536 : 22857 : s->parallelModeLevel = 0;
5537 [ + + - + ]: 22857 : s->parallelChildXact = (p->parallelModeLevel != 0 || p->parallelChildXact);
5538 : 22857 : s->topXidLogged = false;
5539 : :
5540 : 22857 : CurrentTransactionState = s;
5541 : :
5542 : : /*
5543 : : * AbortSubTransaction and CleanupSubTransaction have to be able to cope
5544 : : * with the subtransaction from here on out; in particular they should not
5545 : : * assume that it necessarily has a transaction context, resource owner,
5546 : : * or XID.
5547 : : */
5548 : 22857 : }
5549 : :
5550 : : /*
5551 : : * PopTransaction
5552 : : * Pop back to parent transaction state
5553 : : *
5554 : : * The caller has to make sure to always reassign CurrentTransactionState
5555 : : * if it has a local pointer to it after calling this function.
5556 : : */
5557 : : static void
5558 : 22857 : PopTransaction(void)
5559 : : {
5560 : 22857 : TransactionState s = CurrentTransactionState;
5561 : :
5562 [ - + ]: 22857 : if (s->state != TRANS_DEFAULT)
5563 [ # # ]: 0 : elog(WARNING, "PopTransaction while in %s state",
5564 : : TransStateAsString(s->state));
5565 : :
5566 [ - + ]: 22857 : if (s->parent == NULL)
5567 [ # # ]: 0 : elog(FATAL, "PopTransaction with no parent");
5568 : :
5569 : 22857 : CurrentTransactionState = s->parent;
5570 : :
5571 : : /* Let's just make sure CurTransactionContext is good */
5572 : 22857 : CurTransactionContext = s->parent->curTransactionContext;
5573 : 22857 : MemoryContextSwitchTo(CurTransactionContext);
5574 : :
5575 : : /* Ditto for ResourceOwner links */
5576 : 22857 : CurTransactionResourceOwner = s->parent->curTransactionOwner;
5577 : 22857 : CurrentResourceOwner = s->parent->curTransactionOwner;
5578 : :
5579 : : /* Free the old child structure */
5580 [ + + ]: 22857 : if (s->name)
5581 : 2197 : pfree(s->name);
5582 : 22857 : pfree(s);
5583 : 22857 : }
5584 : :
5585 : : /*
5586 : : * EstimateTransactionStateSpace
5587 : : * Estimate the amount of space that will be needed by
5588 : : * SerializeTransactionState. It would be OK to overestimate slightly,
5589 : : * but it's simple for us to work out the precise value, so we do.
5590 : : */
5591 : : Size
5592 : 669 : EstimateTransactionStateSpace(void)
5593 : : {
5594 : : TransactionState s;
5595 : 669 : Size nxids = 0;
5596 : 669 : Size size = SerializedTransactionStateHeaderSize;
5597 : :
5598 [ + + ]: 3030 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5599 : : {
5600 [ + + ]: 2361 : if (FullTransactionIdIsValid(s->fullTransactionId))
5601 : 1359 : nxids = add_size(nxids, 1);
5602 : 2361 : nxids = add_size(nxids, s->nChildXids);
5603 : : }
5604 : :
5605 : 669 : return add_size(size, mul_size(sizeof(TransactionId), nxids));
5606 : : }
5607 : :
5608 : : /*
5609 : : * SerializeTransactionState
5610 : : * Write out relevant details of our transaction state that will be
5611 : : * needed by a parallel worker.
5612 : : *
5613 : : * We need to save and restore XactDeferrable, XactIsoLevel, and the XIDs
5614 : : * associated with this transaction. These are serialized into a
5615 : : * caller-supplied buffer big enough to hold the number of bytes reported by
5616 : : * EstimateTransactionStateSpace(). We emit the XIDs in sorted order for the
5617 : : * convenience of the receiving process.
5618 : : */
5619 : : void
5620 : 669 : SerializeTransactionState(Size maxsize, char *start_address)
5621 : : {
5622 : : TransactionState s;
5623 : 669 : Size nxids = 0;
5624 : 669 : Size i = 0;
5625 : : TransactionId *workspace;
5626 : : SerializedTransactionState *result;
5627 : :
5628 : 669 : result = (SerializedTransactionState *) start_address;
5629 : :
5630 : 669 : result->xactIsoLevel = XactIsoLevel;
5631 : 669 : result->xactDeferrable = XactDeferrable;
5632 : 669 : result->topFullTransactionId = XactTopFullTransactionId;
5633 : 669 : result->currentFullTransactionId =
5634 : 669 : CurrentTransactionState->fullTransactionId;
5635 : 669 : result->currentCommandId = currentCommandId;
5636 : :
5637 : : /*
5638 : : * If we're running in a parallel worker and launching a parallel worker
5639 : : * of our own, we can just pass along the information that was passed to
5640 : : * us.
5641 : : */
5642 [ - + ]: 669 : if (nParallelCurrentXids > 0)
5643 : : {
5644 : 0 : result->nParallelCurrentXids = nParallelCurrentXids;
5645 : 0 : memcpy(&result->parallelCurrentXids[0], ParallelCurrentXids,
5646 : : nParallelCurrentXids * sizeof(TransactionId));
5647 : 0 : return;
5648 : : }
5649 : :
5650 : : /*
5651 : : * OK, we need to generate a sorted list of XIDs that our workers should
5652 : : * view as current. First, figure out how many there are.
5653 : : */
5654 [ + + ]: 3030 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5655 : : {
5656 [ + + ]: 2361 : if (FullTransactionIdIsValid(s->fullTransactionId))
5657 : 1359 : nxids = add_size(nxids, 1);
5658 : 2361 : nxids = add_size(nxids, s->nChildXids);
5659 : : }
5660 : : Assert(SerializedTransactionStateHeaderSize + nxids * sizeof(TransactionId)
5661 : : <= maxsize);
5662 : :
5663 : : /* Copy them to our scratch space. */
5664 : 669 : workspace = palloc_array(TransactionId, nxids);
5665 [ + + ]: 3030 : for (s = CurrentTransactionState; s != NULL; s = s->parent)
5666 : : {
5667 [ + + ]: 2361 : if (FullTransactionIdIsValid(s->fullTransactionId))
5668 : 1359 : workspace[i++] = XidFromFullTransactionId(s->fullTransactionId);
5669 [ - + ]: 2361 : if (s->nChildXids > 0)
5670 : 0 : memcpy(&workspace[i], s->childXids,
5671 : 0 : s->nChildXids * sizeof(TransactionId));
5672 : 2361 : i += s->nChildXids;
5673 : : }
5674 : : Assert(i == nxids);
5675 : :
5676 : : /* Sort them. */
5677 : 669 : qsort(workspace, nxids, sizeof(TransactionId), xidComparator);
5678 : :
5679 : : /* Copy data into output area. */
5680 : 669 : result->nParallelCurrentXids = nxids;
5681 : 669 : memcpy(&result->parallelCurrentXids[0], workspace,
5682 : : nxids * sizeof(TransactionId));
5683 : : }
5684 : :
5685 : : /*
5686 : : * StartParallelWorkerTransaction
5687 : : * Start a parallel worker transaction, restoring the relevant
5688 : : * transaction state serialized by SerializeTransactionState.
5689 : : */
5690 : : void
5691 : 1995 : StartParallelWorkerTransaction(char *tstatespace)
5692 : : {
5693 : : SerializedTransactionState *tstate;
5694 : :
5695 : : Assert(CurrentTransactionState->blockState == TBLOCK_DEFAULT);
5696 : 1995 : StartTransaction();
5697 : :
5698 : 1995 : tstate = (SerializedTransactionState *) tstatespace;
5699 : 1995 : XactIsoLevel = tstate->xactIsoLevel;
5700 : 1995 : XactDeferrable = tstate->xactDeferrable;
5701 : 1995 : XactTopFullTransactionId = tstate->topFullTransactionId;
5702 : 1995 : CurrentTransactionState->fullTransactionId =
5703 : : tstate->currentFullTransactionId;
5704 : 1995 : currentCommandId = tstate->currentCommandId;
5705 : 1995 : nParallelCurrentXids = tstate->nParallelCurrentXids;
5706 : 1995 : ParallelCurrentXids = &tstate->parallelCurrentXids[0];
5707 : :
5708 : 1995 : CurrentTransactionState->blockState = TBLOCK_PARALLEL_INPROGRESS;
5709 : 1995 : }
5710 : :
5711 : : /*
5712 : : * EndParallelWorkerTransaction
5713 : : * End a parallel worker transaction.
5714 : : */
5715 : : void
5716 : 1987 : EndParallelWorkerTransaction(void)
5717 : : {
5718 : : Assert(CurrentTransactionState->blockState == TBLOCK_PARALLEL_INPROGRESS);
5719 : 1987 : CommitTransaction();
5720 : 1987 : CurrentTransactionState->blockState = TBLOCK_DEFAULT;
5721 : 1987 : }
5722 : :
5723 : : /*
5724 : : * ShowTransactionState
5725 : : * Debug support
5726 : : */
5727 : : static void
5728 : 1315600 : ShowTransactionState(const char *str)
5729 : : {
5730 : : /* skip work if message will definitely not be printed */
5731 [ - + ]: 1315600 : if (message_level_is_interesting(DEBUG5))
5732 : 0 : ShowTransactionStateRec(str, CurrentTransactionState);
5733 : 1315600 : }
5734 : :
5735 : : /*
5736 : : * ShowTransactionStateRec
5737 : : * Recursive subroutine for ShowTransactionState
5738 : : */
5739 : : static void
5740 : 0 : ShowTransactionStateRec(const char *str, TransactionState s)
5741 : : {
5742 : : StringInfoData buf;
5743 : :
5744 [ # # ]: 0 : if (s->parent)
5745 : : {
5746 : : /*
5747 : : * Since this function recurses, it could be driven to stack overflow.
5748 : : * This is just a debugging aid, so we can leave out some details
5749 : : * instead of erroring out with check_stack_depth().
5750 : : */
5751 [ # # ]: 0 : if (stack_is_too_deep())
5752 [ # # ]: 0 : ereport(DEBUG5,
5753 : : (errmsg_internal("%s(%d): parent omitted to avoid stack overflow",
5754 : : str, s->nestingLevel)));
5755 : : else
5756 : 0 : ShowTransactionStateRec(str, s->parent);
5757 : : }
5758 : :
5759 : 0 : initStringInfo(&buf);
5760 [ # # ]: 0 : if (s->nChildXids > 0)
5761 : : {
5762 : : int i;
5763 : :
5764 : 0 : appendStringInfo(&buf, ", children: %u", s->childXids[0]);
5765 [ # # ]: 0 : for (i = 1; i < s->nChildXids; i++)
5766 : 0 : appendStringInfo(&buf, " %u", s->childXids[i]);
5767 : : }
5768 [ # # # # : 0 : ereport(DEBUG5,
# # ]
5769 : : (errmsg_internal("%s(%d) name: %s; blockState: %s; state: %s, xid/subid/cid: %u/%u/%u%s%s",
5770 : : str, s->nestingLevel,
5771 : : s->name ? s->name : "unnamed",
5772 : : BlockStateAsString(s->blockState),
5773 : : TransStateAsString(s->state),
5774 : : XidFromFullTransactionId(s->fullTransactionId),
5775 : : s->subTransactionId,
5776 : : currentCommandId,
5777 : : currentCommandIdUsed ? " (used)" : "",
5778 : : buf.data)));
5779 : 0 : pfree(buf.data);
5780 : 0 : }
5781 : :
5782 : : /*
5783 : : * BlockStateAsString
5784 : : * Debug support
5785 : : */
5786 : : static const char *
5787 : 0 : BlockStateAsString(TBlockState blockState)
5788 : : {
5789 [ # # # # : 0 : switch (blockState)
# # # # #
# # # # #
# # # # #
# # ]
5790 : : {
5791 : 0 : case TBLOCK_DEFAULT:
5792 : 0 : return "DEFAULT";
5793 : 0 : case TBLOCK_STARTED:
5794 : 0 : return "STARTED";
5795 : 0 : case TBLOCK_BEGIN:
5796 : 0 : return "BEGIN";
5797 : 0 : case TBLOCK_INPROGRESS:
5798 : 0 : return "INPROGRESS";
5799 : 0 : case TBLOCK_IMPLICIT_INPROGRESS:
5800 : 0 : return "IMPLICIT_INPROGRESS";
5801 : 0 : case TBLOCK_PARALLEL_INPROGRESS:
5802 : 0 : return "PARALLEL_INPROGRESS";
5803 : 0 : case TBLOCK_END:
5804 : 0 : return "END";
5805 : 0 : case TBLOCK_ABORT:
5806 : 0 : return "ABORT";
5807 : 0 : case TBLOCK_ABORT_END:
5808 : 0 : return "ABORT_END";
5809 : 0 : case TBLOCK_ABORT_PENDING:
5810 : 0 : return "ABORT_PENDING";
5811 : 0 : case TBLOCK_PREPARE:
5812 : 0 : return "PREPARE";
5813 : 0 : case TBLOCK_SUBBEGIN:
5814 : 0 : return "SUBBEGIN";
5815 : 0 : case TBLOCK_SUBINPROGRESS:
5816 : 0 : return "SUBINPROGRESS";
5817 : 0 : case TBLOCK_SUBRELEASE:
5818 : 0 : return "SUBRELEASE";
5819 : 0 : case TBLOCK_SUBCOMMIT:
5820 : 0 : return "SUBCOMMIT";
5821 : 0 : case TBLOCK_SUBABORT:
5822 : 0 : return "SUBABORT";
5823 : 0 : case TBLOCK_SUBABORT_END:
5824 : 0 : return "SUBABORT_END";
5825 : 0 : case TBLOCK_SUBABORT_PENDING:
5826 : 0 : return "SUBABORT_PENDING";
5827 : 0 : case TBLOCK_SUBRESTART:
5828 : 0 : return "SUBRESTART";
5829 : 0 : case TBLOCK_SUBABORT_RESTART:
5830 : 0 : return "SUBABORT_RESTART";
5831 : : }
5832 : 0 : return "UNRECOGNIZED";
5833 : : }
5834 : :
5835 : : /*
5836 : : * TransStateAsString
5837 : : * Debug support
5838 : : */
5839 : : static const char *
5840 : 0 : TransStateAsString(TransState state)
5841 : : {
5842 [ # # # # : 0 : switch (state)
# # # ]
5843 : : {
5844 : 0 : case TRANS_DEFAULT:
5845 : 0 : return "DEFAULT";
5846 : 0 : case TRANS_START:
5847 : 0 : return "START";
5848 : 0 : case TRANS_INPROGRESS:
5849 : 0 : return "INPROGRESS";
5850 : 0 : case TRANS_COMMIT:
5851 : 0 : return "COMMIT";
5852 : 0 : case TRANS_ABORT:
5853 : 0 : return "ABORT";
5854 : 0 : case TRANS_PREPARE:
5855 : 0 : return "PREPARE";
5856 : : }
5857 : 0 : return "UNRECOGNIZED";
5858 : : }
5859 : :
5860 : : /*
5861 : : * xactGetCommittedChildren
5862 : : *
5863 : : * Gets the list of committed children of the current transaction. The return
5864 : : * value is the number of child transactions. *ptr is set to point to an
5865 : : * array of TransactionIds. The array is allocated in TopTransactionContext;
5866 : : * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
5867 : : * If there are no subxacts, *ptr is set to NULL.
5868 : : */
5869 : : int
5870 : 621343 : xactGetCommittedChildren(TransactionId **ptr)
5871 : : {
5872 : 621343 : TransactionState s = CurrentTransactionState;
5873 : :
5874 [ + + ]: 621343 : if (s->nChildXids == 0)
5875 : 620716 : *ptr = NULL;
5876 : : else
5877 : 627 : *ptr = s->childXids;
5878 : :
5879 : 621343 : return s->nChildXids;
5880 : : }
5881 : :
5882 : : /*
5883 : : * XLOG support routines
5884 : : */
5885 : :
5886 : :
5887 : : /*
5888 : : * Log the commit record for a plain or twophase transaction commit.
5889 : : *
5890 : : * A 2pc commit will be emitted when twophase_xid is valid, a plain one
5891 : : * otherwise.
5892 : : */
5893 : : XLogRecPtr
5894 : 157578 : XactLogCommitRecord(TimestampTz commit_time,
5895 : : int nsubxacts, TransactionId *subxacts,
5896 : : int nrels, RelFileLocator *rels,
5897 : : int ndroppedstats, xl_xact_stats_item *droppedstats,
5898 : : int nmsgs, SharedInvalidationMessage *msgs,
5899 : : bool relcacheInval,
5900 : : int xactflags, TransactionId twophase_xid,
5901 : : const char *twophase_gid)
5902 : : {
5903 : : xl_xact_commit xlrec;
5904 : : xl_xact_xinfo xl_xinfo;
5905 : : xl_xact_dbinfo xl_dbinfo;
5906 : : xl_xact_subxacts xl_subxacts;
5907 : : xl_xact_relfilelocators xl_relfilelocators;
5908 : : xl_xact_stats_items xl_dropped_stats;
5909 : : xl_xact_invals xl_invals;
5910 : : xl_xact_twophase xl_twophase;
5911 : : xl_xact_origin xl_origin;
5912 : : uint8 info;
5913 : :
5914 : : Assert(CritSectionCount > 0);
5915 : :
5916 : 157578 : xl_xinfo.xinfo = 0;
5917 : :
5918 : : /* decide between a plain and 2pc commit */
5919 [ + + ]: 157578 : if (!TransactionIdIsValid(twophase_xid))
5920 : 157294 : info = XLOG_XACT_COMMIT;
5921 : : else
5922 : 284 : info = XLOG_XACT_COMMIT_PREPARED;
5923 : :
5924 : : /* First figure out and collect all the information needed */
5925 : :
5926 : 157578 : xlrec.xact_time = commit_time;
5927 : :
5928 [ + + ]: 157578 : if (relcacheInval)
5929 : 4553 : xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
5930 [ + + ]: 157578 : if (forceSyncCommit)
5931 : 597 : xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
5932 [ + + ]: 157578 : if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
5933 : 63113 : xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
5934 : :
5935 : : /*
5936 : : * Check if the caller would like to ask standbys for immediate feedback
5937 : : * once this commit is applied.
5938 : : */
5939 [ + + ]: 157578 : if (synchronous_commit >= SYNCHRONOUS_COMMIT_REMOTE_APPLY)
5940 : 3 : xl_xinfo.xinfo |= XACT_COMPLETION_APPLY_FEEDBACK;
5941 : :
5942 : : /*
5943 : : * Relcache invalidations requires information about the current database
5944 : : * and so does logical decoding.
5945 : : */
5946 [ + + + + : 157578 : if (nmsgs > 0 || XLogLogicalInfoActive())
+ + ]
5947 : : {
5948 : 111615 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
5949 : 111615 : xl_dbinfo.dbId = MyDatabaseId;
5950 : 111615 : xl_dbinfo.tsId = MyDatabaseTableSpace;
5951 : : }
5952 : :
5953 [ + + ]: 157578 : if (nsubxacts > 0)
5954 : : {
5955 : 520 : xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
5956 : 520 : xl_subxacts.nsubxacts = nsubxacts;
5957 : : }
5958 : :
5959 [ + + ]: 157578 : if (nrels > 0)
5960 : : {
5961 : 12256 : xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
5962 : 12256 : xl_relfilelocators.nrels = nrels;
5963 : 12256 : info |= XLR_SPECIAL_REL_UPDATE;
5964 : : }
5965 : :
5966 [ + + ]: 157578 : if (ndroppedstats > 0)
5967 : : {
5968 : 14672 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
5969 : 14672 : xl_dropped_stats.nitems = ndroppedstats;
5970 : : }
5971 : :
5972 [ + + ]: 157578 : if (nmsgs > 0)
5973 : : {
5974 : 110655 : xl_xinfo.xinfo |= XACT_XINFO_HAS_INVALS;
5975 : 110655 : xl_invals.nmsgs = nmsgs;
5976 : : }
5977 : :
5978 [ + + ]: 157578 : if (TransactionIdIsValid(twophase_xid))
5979 : : {
5980 : 284 : xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
5981 : 284 : xl_twophase.xid = twophase_xid;
5982 : : Assert(twophase_gid != NULL);
5983 : :
5984 [ + + - + ]: 284 : if (XLogLogicalInfoActive())
5985 : 43 : xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
5986 : : }
5987 : :
5988 : : /* dump transaction origin information */
5989 [ + + ]: 157578 : if (replorigin_xact_state.origin != InvalidReplOriginId)
5990 : : {
5991 : 1115 : xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
5992 : :
5993 : 1115 : xl_origin.origin_lsn = replorigin_xact_state.origin_lsn;
5994 : 1115 : xl_origin.origin_timestamp = replorigin_xact_state.origin_timestamp;
5995 : : }
5996 : :
5997 [ + + ]: 157578 : if (xl_xinfo.xinfo != 0)
5998 : 114688 : info |= XLOG_XACT_HAS_INFO;
5999 : :
6000 : : /* Then include all the collected data into the commit record. */
6001 : :
6002 : 157578 : XLogBeginInsert();
6003 : :
6004 : 157578 : XLogRegisterData(&xlrec, sizeof(xl_xact_commit));
6005 : :
6006 [ + + ]: 157578 : if (xl_xinfo.xinfo != 0)
6007 : 114688 : XLogRegisterData(&xl_xinfo.xinfo, sizeof(xl_xinfo.xinfo));
6008 : :
6009 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
6010 : 111615 : XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo));
6011 : :
6012 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
6013 : : {
6014 : 520 : XLogRegisterData(&xl_subxacts,
6015 : : MinSizeOfXactSubxacts);
6016 : 520 : XLogRegisterData(subxacts,
6017 : : nsubxacts * sizeof(TransactionId));
6018 : : }
6019 : :
6020 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
6021 : : {
6022 : 12256 : XLogRegisterData(&xl_relfilelocators,
6023 : : MinSizeOfXactRelfileLocators);
6024 : 12256 : XLogRegisterData(rels,
6025 : : nrels * sizeof(RelFileLocator));
6026 : : }
6027 : :
6028 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
6029 : : {
6030 : 14672 : XLogRegisterData(&xl_dropped_stats,
6031 : : MinSizeOfXactStatsItems);
6032 : 14672 : XLogRegisterData(droppedstats,
6033 : : ndroppedstats * sizeof(xl_xact_stats_item));
6034 : : }
6035 : :
6036 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_INVALS)
6037 : : {
6038 : 110655 : XLogRegisterData(&xl_invals, MinSizeOfXactInvals);
6039 : 110655 : XLogRegisterData(msgs,
6040 : : nmsgs * sizeof(SharedInvalidationMessage));
6041 : : }
6042 : :
6043 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
6044 : : {
6045 : 284 : XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase));
6046 [ + + ]: 284 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
6047 : 43 : XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1);
6048 : : }
6049 : :
6050 [ + + ]: 157578 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
6051 : 1115 : XLogRegisterData(&xl_origin, sizeof(xl_xact_origin));
6052 : :
6053 : : /* we allow filtering by xacts */
6054 : 157578 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
6055 : :
6056 : 157578 : return XLogInsert(RM_XACT_ID, info);
6057 : : }
6058 : :
6059 : : /*
6060 : : * Log the commit record for a plain or twophase transaction abort.
6061 : : *
6062 : : * A 2pc abort will be emitted when twophase_xid is valid, a plain one
6063 : : * otherwise.
6064 : : */
6065 : : XLogRecPtr
6066 : 9322 : XactLogAbortRecord(TimestampTz abort_time,
6067 : : int nsubxacts, TransactionId *subxacts,
6068 : : int nrels, RelFileLocator *rels,
6069 : : int ndroppedstats, xl_xact_stats_item *droppedstats,
6070 : : int xactflags, TransactionId twophase_xid,
6071 : : const char *twophase_gid)
6072 : : {
6073 : : xl_xact_abort xlrec;
6074 : : xl_xact_xinfo xl_xinfo;
6075 : : xl_xact_subxacts xl_subxacts;
6076 : : xl_xact_relfilelocators xl_relfilelocators;
6077 : : xl_xact_stats_items xl_dropped_stats;
6078 : : xl_xact_twophase xl_twophase;
6079 : : xl_xact_dbinfo xl_dbinfo;
6080 : : xl_xact_origin xl_origin;
6081 : :
6082 : : uint8 info;
6083 : :
6084 : : Assert(CritSectionCount > 0);
6085 : :
6086 : 9322 : xl_xinfo.xinfo = 0;
6087 : :
6088 : : /* decide between a plain and 2pc abort */
6089 [ + + ]: 9322 : if (!TransactionIdIsValid(twophase_xid))
6090 : 9270 : info = XLOG_XACT_ABORT;
6091 : : else
6092 : 52 : info = XLOG_XACT_ABORT_PREPARED;
6093 : :
6094 : :
6095 : : /* First figure out and collect all the information needed */
6096 : :
6097 : 9322 : xlrec.xact_time = abort_time;
6098 : :
6099 [ + + ]: 9322 : if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
6100 : 5147 : xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
6101 : :
6102 [ + + ]: 9322 : if (nsubxacts > 0)
6103 : : {
6104 : 109 : xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
6105 : 109 : xl_subxacts.nsubxacts = nsubxacts;
6106 : : }
6107 : :
6108 [ + + ]: 9322 : if (nrels > 0)
6109 : : {
6110 : 1426 : xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
6111 : 1426 : xl_relfilelocators.nrels = nrels;
6112 : 1426 : info |= XLR_SPECIAL_REL_UPDATE;
6113 : : }
6114 : :
6115 [ + + ]: 9322 : if (ndroppedstats > 0)
6116 : : {
6117 : 1991 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
6118 : 1991 : xl_dropped_stats.nitems = ndroppedstats;
6119 : : }
6120 : :
6121 [ + + ]: 9322 : if (TransactionIdIsValid(twophase_xid))
6122 : : {
6123 : 52 : xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
6124 : 52 : xl_twophase.xid = twophase_xid;
6125 : : Assert(twophase_gid != NULL);
6126 : :
6127 [ + + - + ]: 52 : if (XLogLogicalInfoActive())
6128 : 15 : xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
6129 : : }
6130 : :
6131 [ + + + + : 9322 : if (TransactionIdIsValid(twophase_xid) && XLogLogicalInfoActive())
- + ]
6132 : : {
6133 : 15 : xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
6134 : 15 : xl_dbinfo.dbId = MyDatabaseId;
6135 : 15 : xl_dbinfo.tsId = MyDatabaseTableSpace;
6136 : : }
6137 : :
6138 : : /*
6139 : : * Dump transaction origin information. We need this during recovery to
6140 : : * update the replication origin progress.
6141 : : */
6142 [ + + ]: 9322 : if (replorigin_xact_state.origin != InvalidReplOriginId)
6143 : : {
6144 : 28 : xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
6145 : :
6146 : 28 : xl_origin.origin_lsn = replorigin_xact_state.origin_lsn;
6147 : 28 : xl_origin.origin_timestamp = replorigin_xact_state.origin_timestamp;
6148 : : }
6149 : :
6150 [ + + ]: 9322 : if (xl_xinfo.xinfo != 0)
6151 : 5403 : info |= XLOG_XACT_HAS_INFO;
6152 : :
6153 : : /* Then include all the collected data into the abort record. */
6154 : :
6155 : 9322 : XLogBeginInsert();
6156 : :
6157 : 9322 : XLogRegisterData(&xlrec, MinSizeOfXactAbort);
6158 : :
6159 [ + + ]: 9322 : if (xl_xinfo.xinfo != 0)
6160 : 5403 : XLogRegisterData(&xl_xinfo, sizeof(xl_xinfo));
6161 : :
6162 [ + + ]: 9322 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
6163 : 15 : XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo));
6164 : :
6165 [ + + ]: 9322 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
6166 : : {
6167 : 109 : XLogRegisterData(&xl_subxacts,
6168 : : MinSizeOfXactSubxacts);
6169 : 109 : XLogRegisterData(subxacts,
6170 : : nsubxacts * sizeof(TransactionId));
6171 : : }
6172 : :
6173 [ + + ]: 9322 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
6174 : : {
6175 : 1426 : XLogRegisterData(&xl_relfilelocators,
6176 : : MinSizeOfXactRelfileLocators);
6177 : 1426 : XLogRegisterData(rels,
6178 : : nrels * sizeof(RelFileLocator));
6179 : : }
6180 : :
6181 [ + + ]: 9322 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
6182 : : {
6183 : 1991 : XLogRegisterData(&xl_dropped_stats,
6184 : : MinSizeOfXactStatsItems);
6185 : 1991 : XLogRegisterData(droppedstats,
6186 : : ndroppedstats * sizeof(xl_xact_stats_item));
6187 : : }
6188 : :
6189 [ + + ]: 9322 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
6190 : : {
6191 : 52 : XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase));
6192 [ + + ]: 52 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
6193 : 15 : XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1);
6194 : : }
6195 : :
6196 [ + + ]: 9322 : if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
6197 : 28 : XLogRegisterData(&xl_origin, sizeof(xl_xact_origin));
6198 : :
6199 : : /* Include the replication origin */
6200 : 9322 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
6201 : :
6202 : 9322 : return XLogInsert(RM_XACT_ID, info);
6203 : : }
6204 : :
6205 : : /*
6206 : : * Before 9.0 this was a fairly short function, but now it performs many
6207 : : * actions for which the order of execution is critical.
6208 : : */
6209 : : static void
6210 : 23502 : xact_redo_commit(xl_xact_parsed_commit *parsed,
6211 : : TransactionId xid,
6212 : : XLogRecPtr lsn,
6213 : : ReplOriginId origin_id)
6214 : : {
6215 : : TransactionId max_xid;
6216 : : TimestampTz commit_time;
6217 : :
6218 : : Assert(TransactionIdIsValid(xid));
6219 : :
6220 : 23502 : max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
6221 : :
6222 : : /* Make sure nextXid is beyond any XID mentioned in the record. */
6223 : 23502 : AdvanceNextFullTransactionIdPastXid(max_xid);
6224 : :
6225 : : Assert(((parsed->xinfo & XACT_XINFO_HAS_ORIGIN) == 0) ==
6226 : : (origin_id == InvalidReplOriginId));
6227 : :
6228 [ + + ]: 23502 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6229 : 20 : commit_time = parsed->origin_timestamp;
6230 : : else
6231 : 23482 : commit_time = parsed->xact_time;
6232 : :
6233 : : /* Set the transaction commit timestamp and metadata */
6234 : 23502 : TransactionTreeSetCommitTsData(xid, parsed->nsubxacts, parsed->subxacts,
6235 : : commit_time, origin_id);
6236 : :
6237 [ + + ]: 23502 : if (standbyState == STANDBY_DISABLED)
6238 : : {
6239 : : /*
6240 : : * Mark the transaction committed in pg_xact.
6241 : : */
6242 : 2225 : TransactionIdCommitTree(xid, parsed->nsubxacts, parsed->subxacts);
6243 : : }
6244 : : else
6245 : : {
6246 : : /*
6247 : : * If a transaction completion record arrives that has as-yet
6248 : : * unobserved subtransactions then this will not have been fully
6249 : : * handled by the call to RecordKnownAssignedTransactionIds() in the
6250 : : * main recovery loop in PerformWalRecovery(). So we need to do
6251 : : * bookkeeping again to cover that case. This is confusing and it is
6252 : : * easy to think this call is irrelevant, which has happened three
6253 : : * times in development already. Leave it in.
6254 : : */
6255 : 21277 : RecordKnownAssignedTransactionIds(max_xid);
6256 : :
6257 : : /*
6258 : : * Mark the transaction committed in pg_xact. We use async commit
6259 : : * protocol during recovery to provide information on database
6260 : : * consistency for when users try to set hint bits. It is important
6261 : : * that we do not set hint bits until the minRecoveryPoint is past
6262 : : * this commit record. This ensures that if we crash we don't see hint
6263 : : * bits set on changes made by transactions that haven't yet
6264 : : * recovered. It's unlikely but it's good to be safe.
6265 : : */
6266 : 21277 : TransactionIdAsyncCommitTree(xid, parsed->nsubxacts, parsed->subxacts, lsn);
6267 : :
6268 : : /*
6269 : : * We must mark clog before we update the ProcArray.
6270 : : */
6271 : 21277 : ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
6272 : :
6273 : : /*
6274 : : * Send any cache invalidations attached to the commit. We must
6275 : : * maintain the same order of invalidation then release locks as
6276 : : * occurs in CommitTransaction().
6277 : : */
6278 : 21277 : ProcessCommittedInvalidationMessages(parsed->msgs, parsed->nmsgs,
6279 : 21277 : XactCompletionRelcacheInitFileInval(parsed->xinfo),
6280 : : parsed->dbId, parsed->tsId);
6281 : :
6282 : : /*
6283 : : * Release locks, if any. We do this for both two phase and normal one
6284 : : * phase transactions. In effect we are ignoring the prepare phase and
6285 : : * just going straight to lock release.
6286 : : */
6287 [ + + ]: 21277 : if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
6288 : 10327 : StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
6289 : : }
6290 : :
6291 [ + + ]: 23502 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6292 : : {
6293 : : /* recover apply progress */
6294 : 20 : replorigin_advance(origin_id, parsed->origin_lsn, lsn,
6295 : : false /* backward */ , false /* WAL */ );
6296 : : }
6297 : :
6298 : : /* Make sure files supposed to be dropped are dropped */
6299 [ + + ]: 23502 : if (parsed->nrels > 0)
6300 : : {
6301 : : /*
6302 : : * First update minimum recovery point to cover this WAL record. Once
6303 : : * a relation is deleted, there's no going back. The buffer manager
6304 : : * enforces the WAL-first rule for normal updates to relation files,
6305 : : * so that the minimum recovery point is always updated before the
6306 : : * corresponding change in the data file is flushed to disk, but we
6307 : : * have to do the same here since we're bypassing the buffer manager.
6308 : : *
6309 : : * Doing this before deleting the files means that if a deletion fails
6310 : : * for some reason, you cannot start up the system even after restart,
6311 : : * until you fix the underlying situation so that the deletion will
6312 : : * succeed. Alternatively, we could update the minimum recovery point
6313 : : * after deletion, but that would leave a small window where the
6314 : : * WAL-first rule would be violated.
6315 : : */
6316 : 2232 : XLogFlush(lsn);
6317 : :
6318 : : /* Make sure files supposed to be dropped are dropped */
6319 : 2232 : DropRelationFiles(parsed->xlocators, parsed->nrels, true);
6320 : : }
6321 : :
6322 [ + + ]: 23502 : if (parsed->nstats > 0)
6323 : : {
6324 : : /* see equivalent call for relations above */
6325 : 2905 : XLogFlush(lsn);
6326 : :
6327 : 2905 : pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
6328 : : }
6329 : :
6330 : : /*
6331 : : * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
6332 : : * in normal operation. For example, in CREATE DATABASE, we copy all files
6333 : : * from the template database, and then commit the transaction. If we
6334 : : * crash after all the files have been copied but before the commit, you
6335 : : * have files in the data directory without an entry in pg_database. To
6336 : : * minimize the window for that, we use ForceSyncCommit() to rush the
6337 : : * commit record to disk as quick as possible. We have the same window
6338 : : * during recovery, and forcing an XLogFlush() (which updates
6339 : : * minRecoveryPoint during recovery) helps to reduce that problem window,
6340 : : * for any user that requested ForceSyncCommit().
6341 : : */
6342 [ + + ]: 23502 : if (XactCompletionForceSyncCommit(parsed->xinfo))
6343 : 51 : XLogFlush(lsn);
6344 : :
6345 : : /*
6346 : : * If asked by the primary (because someone is waiting for a synchronous
6347 : : * commit = remote_apply), we will need to ask walreceiver to send a reply
6348 : : * immediately.
6349 : : */
6350 [ + + ]: 23502 : if (XactCompletionApplyFeedback(parsed->xinfo))
6351 : 3 : XLogRequestWalReceiverReply();
6352 : 23502 : }
6353 : :
6354 : : /*
6355 : : * Be careful with the order of execution, as with xact_redo_commit().
6356 : : * The two functions are similar but differ in key places.
6357 : : *
6358 : : * Note also that an abort can be for a subtransaction and its children,
6359 : : * not just for a top level abort. That means we have to consider
6360 : : * topxid != xid, whereas in commit we would find topxid == xid always
6361 : : * because subtransaction commit is never WAL logged.
6362 : : */
6363 : : static void
6364 : 1983 : xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid,
6365 : : XLogRecPtr lsn, ReplOriginId origin_id)
6366 : : {
6367 : : TransactionId max_xid;
6368 : :
6369 : : Assert(TransactionIdIsValid(xid));
6370 : :
6371 : : /* Make sure nextXid is beyond any XID mentioned in the record. */
6372 : 1983 : max_xid = TransactionIdLatest(xid,
6373 : : parsed->nsubxacts,
6374 : 1983 : parsed->subxacts);
6375 : 1983 : AdvanceNextFullTransactionIdPastXid(max_xid);
6376 : :
6377 [ + + ]: 1983 : if (standbyState == STANDBY_DISABLED)
6378 : : {
6379 : : /* Mark the transaction aborted in pg_xact, no need for async stuff */
6380 : 20 : TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
6381 : : }
6382 : : else
6383 : : {
6384 : : /*
6385 : : * If a transaction completion record arrives that has as-yet
6386 : : * unobserved subtransactions then this will not have been fully
6387 : : * handled by the call to RecordKnownAssignedTransactionIds() in the
6388 : : * main recovery loop in PerformWalRecovery(). So we need to do
6389 : : * bookkeeping again to cover that case. This is confusing and it is
6390 : : * easy to think this call is irrelevant, which has happened three
6391 : : * times in development already. Leave it in.
6392 : : */
6393 : 1963 : RecordKnownAssignedTransactionIds(max_xid);
6394 : :
6395 : : /* Mark the transaction aborted in pg_xact, no need for async stuff */
6396 : 1963 : TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
6397 : :
6398 : : /*
6399 : : * We must update the ProcArray after we have marked clog.
6400 : : */
6401 : 1963 : ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
6402 : :
6403 : : /*
6404 : : * There are no invalidation messages to send or undo.
6405 : : */
6406 : :
6407 : : /*
6408 : : * Release locks, if any. There are no invalidations to send.
6409 : : */
6410 [ + + ]: 1963 : if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
6411 : 1234 : StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
6412 : : }
6413 : :
6414 [ + + ]: 1983 : if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
6415 : : {
6416 : : /* recover apply progress */
6417 : 5 : replorigin_advance(origin_id, parsed->origin_lsn, lsn,
6418 : : false /* backward */ , false /* WAL */ );
6419 : : }
6420 : :
6421 : : /* Make sure files supposed to be dropped are dropped */
6422 [ + + ]: 1983 : if (parsed->nrels > 0)
6423 : : {
6424 : : /*
6425 : : * See comments about update of minimum recovery point on truncation,
6426 : : * in xact_redo_commit().
6427 : : */
6428 : 343 : XLogFlush(lsn);
6429 : :
6430 : 343 : DropRelationFiles(parsed->xlocators, parsed->nrels, true);
6431 : : }
6432 : :
6433 [ + + ]: 1983 : if (parsed->nstats > 0)
6434 : : {
6435 : : /* see equivalent call for relations above */
6436 : 466 : XLogFlush(lsn);
6437 : :
6438 : 466 : pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
6439 : : }
6440 : 1983 : }
6441 : :
6442 : : void
6443 : 25870 : xact_redo(XLogReaderState *record)
6444 : : {
6445 : 25870 : uint8 info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
6446 : :
6447 : : /* Backup blocks are not used in xact records */
6448 : : Assert(!XLogRecHasAnyBlockRefs(record));
6449 : :
6450 [ + + ]: 25870 : if (info == XLOG_XACT_COMMIT)
6451 : : {
6452 : 23456 : xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
6453 : : xl_xact_parsed_commit parsed;
6454 : :
6455 : 23456 : ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
6456 : 23456 : xact_redo_commit(&parsed, XLogRecGetXid(record),
6457 : 23456 : record->EndRecPtr, XLogRecGetOrigin(record));
6458 : : }
6459 [ + + ]: 2414 : else if (info == XLOG_XACT_COMMIT_PREPARED)
6460 : : {
6461 : 46 : xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
6462 : : xl_xact_parsed_commit parsed;
6463 : :
6464 : 46 : ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
6465 : 46 : xact_redo_commit(&parsed, parsed.twophase_xid,
6466 : 46 : record->EndRecPtr, XLogRecGetOrigin(record));
6467 : :
6468 : : /* Delete TwoPhaseState gxact entry and/or 2PC file. */
6469 : 46 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
6470 : 46 : PrepareRedoRemove(parsed.twophase_xid, false);
6471 : 46 : LWLockRelease(TwoPhaseStateLock);
6472 : : }
6473 [ + + ]: 2368 : else if (info == XLOG_XACT_ABORT)
6474 : : {
6475 : 1958 : xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
6476 : : xl_xact_parsed_abort parsed;
6477 : :
6478 : 1958 : ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
6479 : 1958 : xact_redo_abort(&parsed, XLogRecGetXid(record),
6480 : 1958 : record->EndRecPtr, XLogRecGetOrigin(record));
6481 : : }
6482 [ + + ]: 410 : else if (info == XLOG_XACT_ABORT_PREPARED)
6483 : : {
6484 : 25 : xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
6485 : : xl_xact_parsed_abort parsed;
6486 : :
6487 : 25 : ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
6488 : 25 : xact_redo_abort(&parsed, parsed.twophase_xid,
6489 : 25 : record->EndRecPtr, XLogRecGetOrigin(record));
6490 : :
6491 : : /* Delete TwoPhaseState gxact entry and/or 2PC file. */
6492 : 25 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
6493 : 25 : PrepareRedoRemove(parsed.twophase_xid, false);
6494 : 25 : LWLockRelease(TwoPhaseStateLock);
6495 : : }
6496 [ + + ]: 385 : else if (info == XLOG_XACT_PREPARE)
6497 : : {
6498 : : /*
6499 : : * Store xid and start/end pointers of the WAL record in TwoPhaseState
6500 : : * gxact entry.
6501 : : */
6502 : 81 : LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
6503 : 81 : PrepareRedoAdd(InvalidFullTransactionId,
6504 : 81 : XLogRecGetData(record),
6505 : : record->ReadRecPtr,
6506 : : record->EndRecPtr,
6507 : 81 : XLogRecGetOrigin(record));
6508 : 81 : LWLockRelease(TwoPhaseStateLock);
6509 : : }
6510 [ + + ]: 304 : else if (info == XLOG_XACT_ASSIGNMENT)
6511 : : {
6512 : 22 : xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record);
6513 : :
6514 [ + - ]: 22 : if (standbyState >= STANDBY_INITIALIZED)
6515 : 22 : ProcArrayApplyXidAssignment(xlrec->xtop,
6516 : 22 : xlrec->nsubxacts, xlrec->xsub);
6517 : : }
6518 [ - + ]: 282 : else if (info == XLOG_XACT_INVALIDATIONS)
6519 : : {
6520 : : /*
6521 : : * XXX we do ignore this for now, what matters are invalidations
6522 : : * written into the commit record.
6523 : : */
6524 : : }
6525 : : else
6526 [ # # ]: 0 : elog(PANIC, "xact_redo: unknown op code %u", info);
6527 : 25870 : }
|