~ubuntu-branches/ubuntu/natty/postgresql-8.4/natty-updates

« back to all changes in this revision

Viewing changes to src/backend/access/transam/xact.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2009, PostgreSQL Global Development Group
 
9
 * Portions Copyright (c) 1994, Regents of the University of California
 
10
 *
 
11
 *
 
12
 * IDENTIFICATION
 
13
 *        $PostgreSQL$
 
14
 *
 
15
 *-------------------------------------------------------------------------
 
16
 */
 
17
 
 
18
#include "postgres.h"
 
19
 
 
20
#include <time.h>
 
21
#include <unistd.h>
 
22
 
 
23
#include "access/multixact.h"
 
24
#include "access/subtrans.h"
 
25
#include "access/transam.h"
 
26
#include "access/twophase.h"
 
27
#include "access/xact.h"
 
28
#include "access/xlogutils.h"
 
29
#include "catalog/catalog.h"
 
30
#include "catalog/namespace.h"
 
31
#include "catalog/storage.h"
 
32
#include "commands/async.h"
 
33
#include "commands/tablecmds.h"
 
34
#include "commands/trigger.h"
 
35
#include "executor/spi.h"
 
36
#include "libpq/be-fsstubs.h"
 
37
#include "miscadmin.h"
 
38
#include "pgstat.h"
 
39
#include "storage/bufmgr.h"
 
40
#include "storage/fd.h"
 
41
#include "storage/lmgr.h"
 
42
#include "storage/procarray.h"
 
43
#include "storage/sinvaladt.h"
 
44
#include "storage/smgr.h"
 
45
#include "utils/combocid.h"
 
46
#include "utils/flatfiles.h"
 
47
#include "utils/guc.h"
 
48
#include "utils/inval.h"
 
49
#include "utils/memutils.h"
 
50
#include "utils/relcache.h"
 
51
#include "utils/snapmgr.h"
 
52
#include "utils/xml.h"
 
53
#include "pg_trace.h"
 
54
 
 
55
 
 
56
/*
 
57
 *      User-tweakable parameters
 
58
 */
 
59
int                     DefaultXactIsoLevel = XACT_READ_COMMITTED;
 
60
int                     XactIsoLevel;
 
61
 
 
62
bool            DefaultXactReadOnly = false;
 
63
bool            XactReadOnly;
 
64
 
 
65
bool            XactSyncCommit = true;
 
66
 
 
67
int                     CommitDelay = 0;        /* precommit delay in microseconds */
 
68
int                     CommitSiblings = 5; /* # concurrent xacts needed to sleep */
 
69
 
 
70
/*
 
71
 * MyXactAccessedTempRel is set when a temporary relation is accessed.
 
72
 * We don't allow PREPARE TRANSACTION in that case.  (This is global
 
73
 * so that it can be set from heapam.c.)
 
74
 */
 
75
bool            MyXactAccessedTempRel = false;
 
76
 
 
77
 
 
78
/*
 
79
 *      transaction states - transaction state from server perspective
 
80
 */
 
81
typedef enum TransState
 
82
{
 
83
        TRANS_DEFAULT,                          /* idle */
 
84
        TRANS_START,                            /* transaction starting */
 
85
        TRANS_INPROGRESS,                       /* inside a valid transaction */
 
86
        TRANS_COMMIT,                           /* commit in progress */
 
87
        TRANS_ABORT,                            /* abort in progress */
 
88
        TRANS_PREPARE                           /* prepare in progress */
 
89
} TransState;
 
90
 
 
91
/*
 
92
 *      transaction block states - transaction state of client queries
 
93
 *
 
94
 * Note: the subtransaction states are used only for non-topmost
 
95
 * transactions; the others appear only in the topmost transaction.
 
96
 */
 
97
typedef enum TBlockState
 
98
{
 
99
        /* not-in-transaction-block states */
 
100
        TBLOCK_DEFAULT,                         /* idle */
 
101
        TBLOCK_STARTED,                         /* running single-query transaction */
 
102
 
 
103
        /* transaction block states */
 
104
        TBLOCK_BEGIN,                           /* starting transaction block */
 
105
        TBLOCK_INPROGRESS,                      /* live transaction */
 
106
        TBLOCK_END,                                     /* COMMIT received */
 
107
        TBLOCK_ABORT,                           /* failed xact, awaiting ROLLBACK */
 
108
        TBLOCK_ABORT_END,                       /* failed xact, ROLLBACK received */
 
109
        TBLOCK_ABORT_PENDING,           /* live xact, ROLLBACK received */
 
110
        TBLOCK_PREPARE,                         /* live xact, PREPARE received */
 
111
 
 
112
        /* subtransaction states */
 
113
        TBLOCK_SUBBEGIN,                        /* starting a subtransaction */
 
114
        TBLOCK_SUBINPROGRESS,           /* live subtransaction */
 
115
        TBLOCK_SUBEND,                          /* RELEASE received */
 
116
        TBLOCK_SUBABORT,                        /* failed subxact, awaiting ROLLBACK */
 
117
        TBLOCK_SUBABORT_END,            /* failed subxact, ROLLBACK received */
 
118
        TBLOCK_SUBABORT_PENDING,        /* live subxact, ROLLBACK received */
 
119
        TBLOCK_SUBRESTART,                      /* live subxact, ROLLBACK TO received */
 
120
        TBLOCK_SUBABORT_RESTART         /* failed subxact, ROLLBACK TO received */
 
121
} TBlockState;
 
122
 
 
123
/*
 
124
 *      transaction state structure
 
125
 */
 
126
typedef struct TransactionStateData
 
127
{
 
128
        TransactionId transactionId;    /* my XID, or Invalid if none */
 
129
        SubTransactionId subTransactionId;      /* my subxact ID */
 
130
        char       *name;                       /* savepoint name, if any */
 
131
        int                     savepointLevel; /* savepoint level */
 
132
        TransState      state;                  /* low-level state */
 
133
        TBlockState blockState;         /* high-level state */
 
134
        int                     nestingLevel;   /* transaction nesting depth */
 
135
        int                     gucNestLevel;   /* GUC context nesting depth */
 
136
        MemoryContext curTransactionContext;            /* my xact-lifetime context */
 
137
        ResourceOwner curTransactionOwner;      /* my query resources */
 
138
        TransactionId *childXids;       /* subcommitted child XIDs, in XID order */
 
139
        int                     nChildXids;             /* # of subcommitted child XIDs */
 
140
        int                     maxChildXids;   /* allocated size of childXids[] */
 
141
        Oid                     prevUser;               /* previous CurrentUserId setting */
 
142
        bool            prevSecDefCxt;  /* previous SecurityDefinerContext setting */
 
143
        bool            prevXactReadOnly;               /* entry-time xact r/o state */
 
144
        struct TransactionStateData *parent;            /* back link to parent */
 
145
} TransactionStateData;
 
146
 
 
147
typedef TransactionStateData *TransactionState;
 
148
 
 
149
/*
 
150
 * CurrentTransactionState always points to the current transaction state
 
151
 * block.  It will point to TopTransactionStateData when not in a
 
152
 * transaction at all, or when in a top-level transaction.
 
153
 */
 
154
static TransactionStateData TopTransactionStateData = {
 
155
        0,                                                      /* transaction id */
 
156
        0,                                                      /* subtransaction id */
 
157
        NULL,                                           /* savepoint name */
 
158
        0,                                                      /* savepoint level */
 
159
        TRANS_DEFAULT,                          /* transaction state */
 
160
        TBLOCK_DEFAULT,                         /* transaction block state from the client
 
161
                                                                 * perspective */
 
162
        0,                                                      /* transaction nesting depth */
 
163
        0,                                                      /* GUC context nesting depth */
 
164
        NULL,                                           /* cur transaction context */
 
165
        NULL,                                           /* cur transaction resource owner */
 
166
        NULL,                                           /* subcommitted child Xids */
 
167
        0,                                                      /* # of subcommitted child Xids */
 
168
        0,                                                      /* allocated size of childXids[] */
 
169
        InvalidOid,                                     /* previous CurrentUserId setting */
 
170
        false,                                          /* previous SecurityDefinerContext setting */
 
171
        false,                                          /* entry-time xact r/o state */
 
172
        NULL                                            /* link to parent state block */
 
173
};
 
174
 
 
175
static TransactionState CurrentTransactionState = &TopTransactionStateData;
 
176
 
 
177
/*
 
178
 * The subtransaction ID and command ID assignment counters are global
 
179
 * to a whole transaction, so we do not keep them in the state stack.
 
180
 */
 
181
static SubTransactionId currentSubTransactionId;
 
182
static CommandId currentCommandId;
 
183
static bool currentCommandIdUsed;
 
184
 
 
185
/*
 
186
 * xactStartTimestamp is the value of transaction_timestamp().
 
187
 * stmtStartTimestamp is the value of statement_timestamp().
 
188
 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
 
189
 * These do not change as we enter and exit subtransactions, so we don't
 
190
 * keep them inside the TransactionState stack.
 
191
 */
 
192
static TimestampTz xactStartTimestamp;
 
193
static TimestampTz stmtStartTimestamp;
 
194
static TimestampTz xactStopTimestamp;
 
195
 
 
196
/*
 
197
 * GID to be used for preparing the current transaction.  This is also
 
198
 * global to a whole transaction, so we don't keep it in the state stack.
 
199
 */
 
200
static char *prepareGID;
 
201
 
 
202
/*
 
203
 * Some commands want to force synchronous commit.
 
204
 */
 
205
static bool forceSyncCommit = false;
 
206
 
 
207
/*
 
208
 * Private context for transaction-abort work --- we reserve space for this
 
209
 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
 
210
 * when we've run out of memory.
 
211
 */
 
212
static MemoryContext TransactionAbortContext = NULL;
 
213
 
 
214
/*
 
215
 * List of add-on start- and end-of-xact callbacks
 
216
 */
 
217
typedef struct XactCallbackItem
 
218
{
 
219
        struct XactCallbackItem *next;
 
220
        XactCallback callback;
 
221
        void       *arg;
 
222
} XactCallbackItem;
 
223
 
 
224
static XactCallbackItem *Xact_callbacks = NULL;
 
225
 
 
226
/*
 
227
 * List of add-on start- and end-of-subxact callbacks
 
228
 */
 
229
typedef struct SubXactCallbackItem
 
230
{
 
231
        struct SubXactCallbackItem *next;
 
232
        SubXactCallback callback;
 
233
        void       *arg;
 
234
} SubXactCallbackItem;
 
235
 
 
236
static SubXactCallbackItem *SubXact_callbacks = NULL;
 
237
 
 
238
 
 
239
/* local function prototypes */
 
240
static void AssignTransactionId(TransactionState s);
 
241
static void AbortTransaction(void);
 
242
static void AtAbort_Memory(void);
 
243
static void AtCleanup_Memory(void);
 
244
static void AtAbort_ResourceOwner(void);
 
245
static void AtCommit_LocalCache(void);
 
246
static void AtCommit_Memory(void);
 
247
static void AtStart_Cache(void);
 
248
static void AtStart_Memory(void);
 
249
static void AtStart_ResourceOwner(void);
 
250
static void CallXactCallbacks(XactEvent event);
 
251
static void CallSubXactCallbacks(SubXactEvent event,
 
252
                                         SubTransactionId mySubid,
 
253
                                         SubTransactionId parentSubid);
 
254
static void CleanupTransaction(void);
 
255
static void CommitTransaction(void);
 
256
static TransactionId RecordTransactionAbort(bool isSubXact);
 
257
static void StartTransaction(void);
 
258
 
 
259
static void StartSubTransaction(void);
 
260
static void CommitSubTransaction(void);
 
261
static void AbortSubTransaction(void);
 
262
static void CleanupSubTransaction(void);
 
263
static void PushTransaction(void);
 
264
static void PopTransaction(void);
 
265
 
 
266
static void AtSubAbort_Memory(void);
 
267
static void AtSubCleanup_Memory(void);
 
268
static void AtSubAbort_ResourceOwner(void);
 
269
static void AtSubCommit_Memory(void);
 
270
static void AtSubStart_Memory(void);
 
271
static void AtSubStart_ResourceOwner(void);
 
272
 
 
273
static void ShowTransactionState(const char *str);
 
274
static void ShowTransactionStateRec(TransactionState state);
 
275
static const char *BlockStateAsString(TBlockState blockState);
 
276
static const char *TransStateAsString(TransState state);
 
277
 
 
278
 
 
279
/* ----------------------------------------------------------------
 
280
 *      transaction state accessors
 
281
 * ----------------------------------------------------------------
 
282
 */
 
283
 
 
284
/*
 
285
 *      IsTransactionState
 
286
 *
 
287
 *      This returns true if we are inside a valid transaction; that is,
 
288
 *      it is safe to initiate database access, take heavyweight locks, etc.
 
289
 */
 
290
bool
 
291
IsTransactionState(void)
 
292
{
 
293
        TransactionState s = CurrentTransactionState;
 
294
 
 
295
        /*
 
296
         * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states.  However, we
 
297
         * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
 
298
         * TRANS_PREPARE since it might be too soon or too late within those
 
299
         * transition states to do anything interesting.  Hence, the only "valid"
 
300
         * state is TRANS_INPROGRESS.
 
301
         */
 
302
        return (s->state == TRANS_INPROGRESS);
 
303
}
 
304
 
 
305
/*
 
306
 *      IsAbortedTransactionBlockState
 
307
 *
 
308
 *      This returns true if we are currently running a query
 
309
 *      within an aborted transaction block.
 
310
 */
 
311
bool
 
312
IsAbortedTransactionBlockState(void)
 
313
{
 
314
        TransactionState s = CurrentTransactionState;
 
315
 
 
316
        if (s->blockState == TBLOCK_ABORT ||
 
317
                s->blockState == TBLOCK_SUBABORT)
 
318
                return true;
 
319
 
 
320
        return false;
 
321
}
 
322
 
 
323
 
 
324
/*
 
325
 *      GetTopTransactionId
 
326
 *
 
327
 * This will return the XID of the main transaction, assigning one if
 
328
 * it's not yet set.  Be careful to call this only inside a valid xact.
 
329
 */
 
330
TransactionId
 
331
GetTopTransactionId(void)
 
332
{
 
333
        if (!TransactionIdIsValid(TopTransactionStateData.transactionId))
 
334
                AssignTransactionId(&TopTransactionStateData);
 
335
        return TopTransactionStateData.transactionId;
 
336
}
 
337
 
 
338
/*
 
339
 *      GetTopTransactionIdIfAny
 
340
 *
 
341
 * This will return the XID of the main transaction, if one is assigned.
 
342
 * It will return InvalidTransactionId if we are not currently inside a
 
343
 * transaction, or inside a transaction that hasn't yet been assigned an XID.
 
344
 */
 
345
TransactionId
 
346
GetTopTransactionIdIfAny(void)
 
347
{
 
348
        return TopTransactionStateData.transactionId;
 
349
}
 
350
 
 
351
/*
 
352
 *      GetCurrentTransactionId
 
353
 *
 
354
 * This will return the XID of the current transaction (main or sub
 
355
 * transaction), assigning one if it's not yet set.  Be careful to call this
 
356
 * only inside a valid xact.
 
357
 */
 
358
TransactionId
 
359
GetCurrentTransactionId(void)
 
360
{
 
361
        TransactionState s = CurrentTransactionState;
 
362
 
 
363
        if (!TransactionIdIsValid(s->transactionId))
 
364
                AssignTransactionId(s);
 
365
        return s->transactionId;
 
366
}
 
367
 
 
368
/*
 
369
 *      GetCurrentTransactionIdIfAny
 
370
 *
 
371
 * This will return the XID of the current sub xact, if one is assigned.
 
372
 * It will return InvalidTransactionId if we are not currently inside a
 
373
 * transaction, or inside a transaction that hasn't been assigned an XID yet.
 
374
 */
 
375
TransactionId
 
376
GetCurrentTransactionIdIfAny(void)
 
377
{
 
378
        return CurrentTransactionState->transactionId;
 
379
}
 
380
 
 
381
 
 
382
/*
 
383
 * AssignTransactionId
 
384
 *
 
385
 * Assigns a new permanent XID to the given TransactionState.
 
386
 * We do not assign XIDs to transactions until/unless this is called.
 
387
 * Also, any parent TransactionStates that don't yet have XIDs are assigned
 
388
 * one; this maintains the invariant that a child transaction has an XID
 
389
 * following its parent's.
 
390
 */
 
391
static void
 
392
AssignTransactionId(TransactionState s)
 
393
{
 
394
        bool            isSubXact = (s->parent != NULL);
 
395
        ResourceOwner currentOwner;
 
396
 
 
397
        /* Assert that caller didn't screw up */
 
398
        Assert(!TransactionIdIsValid(s->transactionId));
 
399
        Assert(s->state == TRANS_INPROGRESS);
 
400
 
 
401
        /*
 
402
         * Ensure parent(s) have XIDs, so that a child always has an XID later
 
403
         * than its parent.
 
404
         */
 
405
        if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))
 
406
                AssignTransactionId(s->parent);
 
407
 
 
408
        /*
 
409
         * Generate a new Xid and record it in PG_PROC and pg_subtrans.
 
410
         *
 
411
         * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
 
412
         * shared storage other than PG_PROC; because if there's no room for it in
 
413
         * PG_PROC, the subtrans entry is needed to ensure that other backends see
 
414
         * the Xid as "running".  See GetNewTransactionId.
 
415
         */
 
416
        s->transactionId = GetNewTransactionId(isSubXact);
 
417
 
 
418
        if (isSubXact)
 
419
                SubTransSetParent(s->transactionId, s->parent->transactionId);
 
420
 
 
421
        /*
 
422
         * Acquire lock on the transaction XID.  (We assume this cannot block.) We
 
423
         * have to ensure that the lock is assigned to the transaction's own
 
424
         * ResourceOwner.
 
425
         */
 
426
        currentOwner = CurrentResourceOwner;
 
427
        PG_TRY();
 
428
        {
 
429
                CurrentResourceOwner = s->curTransactionOwner;
 
430
                XactLockTableInsert(s->transactionId);
 
431
        }
 
432
        PG_CATCH();
 
433
        {
 
434
                /* Ensure CurrentResourceOwner is restored on error */
 
435
                CurrentResourceOwner = currentOwner;
 
436
                PG_RE_THROW();
 
437
        }
 
438
        PG_END_TRY();
 
439
        CurrentResourceOwner = currentOwner;
 
440
}
 
441
 
 
442
 
 
443
/*
 
444
 *      GetCurrentSubTransactionId
 
445
 */
 
446
SubTransactionId
 
447
GetCurrentSubTransactionId(void)
 
448
{
 
449
        TransactionState s = CurrentTransactionState;
 
450
 
 
451
        return s->subTransactionId;
 
452
}
 
453
 
 
454
 
 
455
/*
 
456
 *      GetCurrentCommandId
 
457
 *
 
458
 * "used" must be TRUE if the caller intends to use the command ID to mark
 
459
 * inserted/updated/deleted tuples.  FALSE means the ID is being fetched
 
460
 * for read-only purposes (ie, as a snapshot validity cutoff).  See
 
461
 * CommandCounterIncrement() for discussion.
 
462
 */
 
463
CommandId
 
464
GetCurrentCommandId(bool used)
 
465
{
 
466
        /* this is global to a transaction, not subtransaction-local */
 
467
        if (used)
 
468
                currentCommandIdUsed = true;
 
469
        return currentCommandId;
 
470
}
 
471
 
 
472
/*
 
473
 *      GetCurrentTransactionStartTimestamp
 
474
 */
 
475
TimestampTz
 
476
GetCurrentTransactionStartTimestamp(void)
 
477
{
 
478
        return xactStartTimestamp;
 
479
}
 
480
 
 
481
/*
 
482
 *      GetCurrentStatementStartTimestamp
 
483
 */
 
484
TimestampTz
 
485
GetCurrentStatementStartTimestamp(void)
 
486
{
 
487
        return stmtStartTimestamp;
 
488
}
 
489
 
 
490
/*
 
491
 *      GetCurrentTransactionStopTimestamp
 
492
 *
 
493
 * We return current time if the transaction stop time hasn't been set
 
494
 * (which can happen if we decide we don't need to log an XLOG record).
 
495
 */
 
496
TimestampTz
 
497
GetCurrentTransactionStopTimestamp(void)
 
498
{
 
499
        if (xactStopTimestamp != 0)
 
500
                return xactStopTimestamp;
 
501
        return GetCurrentTimestamp();
 
502
}
 
503
 
 
504
/*
 
505
 *      SetCurrentStatementStartTimestamp
 
506
 */
 
507
void
 
508
SetCurrentStatementStartTimestamp(void)
 
509
{
 
510
        stmtStartTimestamp = GetCurrentTimestamp();
 
511
}
 
512
 
 
513
/*
 
514
 *      SetCurrentTransactionStopTimestamp
 
515
 */
 
516
static inline void
 
517
SetCurrentTransactionStopTimestamp(void)
 
518
{
 
519
        xactStopTimestamp = GetCurrentTimestamp();
 
520
}
 
521
 
 
522
/*
 
523
 *      GetCurrentTransactionNestLevel
 
524
 *
 
525
 * Note: this will return zero when not inside any transaction, one when
 
526
 * inside a top-level transaction, etc.
 
527
 */
 
528
int
 
529
GetCurrentTransactionNestLevel(void)
 
530
{
 
531
        TransactionState s = CurrentTransactionState;
 
532
 
 
533
        return s->nestingLevel;
 
534
}
 
535
 
 
536
 
 
537
/*
 
538
 *      TransactionIdIsCurrentTransactionId
 
539
 */
 
540
bool
 
541
TransactionIdIsCurrentTransactionId(TransactionId xid)
 
542
{
 
543
        TransactionState s;
 
544
 
 
545
        /*
 
546
         * We always say that BootstrapTransactionId is "not my transaction ID"
 
547
         * even when it is (ie, during bootstrap).      Along with the fact that
 
548
         * transam.c always treats BootstrapTransactionId as already committed,
 
549
         * this causes the tqual.c routines to see all tuples as committed, which
 
550
         * is what we need during bootstrap.  (Bootstrap mode only inserts tuples,
 
551
         * it never updates or deletes them, so all tuples can be presumed good
 
552
         * immediately.)
 
553
         *
 
554
         * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
 
555
         * not my transaction ID, so we can just return "false" immediately for
 
556
         * any non-normal XID.
 
557
         */
 
558
        if (!TransactionIdIsNormal(xid))
 
559
                return false;
 
560
 
 
561
        /*
 
562
         * We will return true for the Xid of the current subtransaction, any of
 
563
         * its subcommitted children, any of its parents, or any of their
 
564
         * previously subcommitted children.  However, a transaction being aborted
 
565
         * is no longer "current", even though it may still have an entry on the
 
566
         * state stack.
 
567
         */
 
568
        for (s = CurrentTransactionState; s != NULL; s = s->parent)
 
569
        {
 
570
                int low, high;
 
571
 
 
572
                if (s->state == TRANS_ABORT)
 
573
                        continue;
 
574
                if (!TransactionIdIsValid(s->transactionId))
 
575
                        continue;                       /* it can't have any child XIDs either */
 
576
                if (TransactionIdEquals(xid, s->transactionId))
 
577
                        return true;
 
578
                /* As the childXids array is ordered, we can use binary search */
 
579
                low = 0;
 
580
                high = s->nChildXids - 1;
 
581
                while (low <= high)
 
582
                {
 
583
                        int                             middle;
 
584
                        TransactionId   probe;
 
585
 
 
586
                        middle = low + (high - low) / 2;
 
587
                        probe = s->childXids[middle];
 
588
                        if (TransactionIdEquals(probe, xid))
 
589
                                return true;
 
590
                        else if (TransactionIdPrecedes(probe, xid))
 
591
                                low = middle + 1;
 
592
                        else
 
593
                                high = middle - 1;
 
594
                }
 
595
        }
 
596
 
 
597
        return false;
 
598
}
 
599
 
 
600
 
 
601
/*
 
602
 *      CommandCounterIncrement
 
603
 */
 
604
void
 
605
CommandCounterIncrement(void)
 
606
{
 
607
        /*
 
608
         * If the current value of the command counter hasn't been "used" to
 
609
         * mark tuples, we need not increment it, since there's no need to
 
610
         * distinguish a read-only command from others.  This helps postpone
 
611
         * command counter overflow, and keeps no-op CommandCounterIncrement
 
612
         * operations cheap.
 
613
         */
 
614
        if (currentCommandIdUsed)
 
615
        {
 
616
                currentCommandId += 1;
 
617
                if (currentCommandId == FirstCommandId) /* check for overflow */
 
618
                {
 
619
                        currentCommandId -= 1;
 
620
                        ereport(ERROR,
 
621
                                        (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 
622
                  errmsg("cannot have more than 2^32-1 commands in a transaction")));
 
623
                }
 
624
                currentCommandIdUsed = false;
 
625
 
 
626
                /* Propagate new command ID into static snapshots */
 
627
                SnapshotSetCommandId(currentCommandId);
 
628
                
 
629
                /*
 
630
                 * Make any catalog changes done by the just-completed command
 
631
                 * visible in the local syscache.  We obviously don't need to do
 
632
                 * this after a read-only command.  (But see hacks in inval.c
 
633
                 * to make real sure we don't think a command that queued inval
 
634
                 * messages was read-only.)
 
635
                 */
 
636
                AtCommit_LocalCache();
 
637
        }
 
638
 
 
639
        /*
 
640
         * Make any other backends' catalog changes visible to me.
 
641
         *
 
642
         * XXX this is probably in the wrong place: CommandCounterIncrement
 
643
         * should be purely a local operation, most likely.  However fooling
 
644
         * with this will affect asynchronous cross-backend interactions,
 
645
         * which doesn't seem like a wise thing to do in late beta, so save
 
646
         * improving this for another day - tgl 2007-11-30
 
647
         */
 
648
        AtStart_Cache();
 
649
}
 
650
 
 
651
/*
 
652
 * ForceSyncCommit
 
653
 *
 
654
 * Interface routine to allow commands to force a synchronous commit of the
 
655
 * current top-level transaction
 
656
 */
 
657
void
 
658
ForceSyncCommit(void)
 
659
{
 
660
        forceSyncCommit = true;
 
661
}
 
662
 
 
663
 
 
664
/* ----------------------------------------------------------------
 
665
 *                                              StartTransaction stuff
 
666
 * ----------------------------------------------------------------
 
667
 */
 
668
 
 
669
/*
 
670
 *      AtStart_Cache
 
671
 */
 
672
static void
 
673
AtStart_Cache(void)
 
674
{
 
675
        AcceptInvalidationMessages();
 
676
}
 
677
 
 
678
/*
 
679
 *      AtStart_Memory
 
680
 */
 
681
static void
 
682
AtStart_Memory(void)
 
683
{
 
684
        TransactionState s = CurrentTransactionState;
 
685
 
 
686
        /*
 
687
         * If this is the first time through, create a private context for
 
688
         * AbortTransaction to work in.  By reserving some space now, we can
 
689
         * insulate AbortTransaction from out-of-memory scenarios.      Like
 
690
         * ErrorContext, we set it up with slow growth rate and a nonzero minimum
 
691
         * size, so that space will be reserved immediately.
 
692
         */
 
693
        if (TransactionAbortContext == NULL)
 
694
                TransactionAbortContext =
 
695
                        AllocSetContextCreate(TopMemoryContext,
 
696
                                                                  "TransactionAbortContext",
 
697
                                                                  32 * 1024,
 
698
                                                                  32 * 1024,
 
699
                                                                  32 * 1024);
 
700
 
 
701
        /*
 
702
         * We shouldn't have a transaction context already.
 
703
         */
 
704
        Assert(TopTransactionContext == NULL);
 
705
 
 
706
        /*
 
707
         * Create a toplevel context for the transaction.
 
708
         */
 
709
        TopTransactionContext =
 
710
                AllocSetContextCreate(TopMemoryContext,
 
711
                                                          "TopTransactionContext",
 
712
                                                          ALLOCSET_DEFAULT_MINSIZE,
 
713
                                                          ALLOCSET_DEFAULT_INITSIZE,
 
714
                                                          ALLOCSET_DEFAULT_MAXSIZE);
 
715
 
 
716
        /*
 
717
         * In a top-level transaction, CurTransactionContext is the same as
 
718
         * TopTransactionContext.
 
719
         */
 
720
        CurTransactionContext = TopTransactionContext;
 
721
        s->curTransactionContext = CurTransactionContext;
 
722
 
 
723
        /* Make the CurTransactionContext active. */
 
724
        MemoryContextSwitchTo(CurTransactionContext);
 
725
}
 
726
 
 
727
/*
 
728
 *      AtStart_ResourceOwner
 
729
 */
 
730
static void
 
731
AtStart_ResourceOwner(void)
 
732
{
 
733
        TransactionState s = CurrentTransactionState;
 
734
 
 
735
        /*
 
736
         * We shouldn't have a transaction resource owner already.
 
737
         */
 
738
        Assert(TopTransactionResourceOwner == NULL);
 
739
 
 
740
        /*
 
741
         * Create a toplevel resource owner for the transaction.
 
742
         */
 
743
        s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
 
744
 
 
745
        TopTransactionResourceOwner = s->curTransactionOwner;
 
746
        CurTransactionResourceOwner = s->curTransactionOwner;
 
747
        CurrentResourceOwner = s->curTransactionOwner;
 
748
}
 
749
 
 
750
/* ----------------------------------------------------------------
 
751
 *                                              StartSubTransaction stuff
 
752
 * ----------------------------------------------------------------
 
753
 */
 
754
 
 
755
/*
 
756
 * AtSubStart_Memory
 
757
 */
 
758
static void
 
759
AtSubStart_Memory(void)
 
760
{
 
761
        TransactionState s = CurrentTransactionState;
 
762
 
 
763
        Assert(CurTransactionContext != NULL);
 
764
 
 
765
        /*
 
766
         * Create a CurTransactionContext, which will be used to hold data that
 
767
         * survives subtransaction commit but disappears on subtransaction abort.
 
768
         * We make it a child of the immediate parent's CurTransactionContext.
 
769
         */
 
770
        CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
 
771
                                                                                                  "CurTransactionContext",
 
772
                                                                                                  ALLOCSET_DEFAULT_MINSIZE,
 
773
                                                                                                  ALLOCSET_DEFAULT_INITSIZE,
 
774
                                                                                                  ALLOCSET_DEFAULT_MAXSIZE);
 
775
        s->curTransactionContext = CurTransactionContext;
 
776
 
 
777
        /* Make the CurTransactionContext active. */
 
778
        MemoryContextSwitchTo(CurTransactionContext);
 
779
}
 
780
 
 
781
/*
 
782
 * AtSubStart_ResourceOwner
 
783
 */
 
784
static void
 
785
AtSubStart_ResourceOwner(void)
 
786
{
 
787
        TransactionState s = CurrentTransactionState;
 
788
 
 
789
        Assert(s->parent != NULL);
 
790
 
 
791
        /*
 
792
         * Create a resource owner for the subtransaction.      We make it a child of
 
793
         * the immediate parent's resource owner.
 
794
         */
 
795
        s->curTransactionOwner =
 
796
                ResourceOwnerCreate(s->parent->curTransactionOwner,
 
797
                                                        "SubTransaction");
 
798
 
 
799
        CurTransactionResourceOwner = s->curTransactionOwner;
 
800
        CurrentResourceOwner = s->curTransactionOwner;
 
801
}
 
802
 
 
803
/* ----------------------------------------------------------------
 
804
 *                                              CommitTransaction stuff
 
805
 * ----------------------------------------------------------------
 
806
 */
 
807
 
 
808
/*
 
809
 *      RecordTransactionCommit
 
810
 *
 
811
 * Returns latest XID among xact and its children, or InvalidTransactionId
 
812
 * if the xact has no XID.      (We compute that here just because it's easier.)
 
813
 *
 
814
 * This is exported only to support an ugly hack in VACUUM FULL.
 
815
 */
 
816
TransactionId
 
817
RecordTransactionCommit(void)
 
818
{
 
819
        TransactionId xid = GetTopTransactionIdIfAny();
 
820
        bool            markXidCommitted = TransactionIdIsValid(xid);
 
821
        TransactionId latestXid = InvalidTransactionId;
 
822
        int                     nrels;
 
823
        RelFileNode *rels;
 
824
        bool            haveNonTemp;
 
825
        int                     nchildren;
 
826
        TransactionId *children;
 
827
 
 
828
        /* Get data needed for commit record */
 
829
        nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp);
 
830
        nchildren = xactGetCommittedChildren(&children);
 
831
 
 
832
        /*
 
833
         * If we haven't been assigned an XID yet, we neither can, nor do we want
 
834
         * to write a COMMIT record.
 
835
         */
 
836
        if (!markXidCommitted)
 
837
        {
 
838
                /*
 
839
                 * We expect that every smgrscheduleunlink is followed by a catalog
 
840
                 * update, and hence XID assignment, so we shouldn't get here with any
 
841
                 * pending deletes.  Use a real test not just an Assert to check this,
 
842
                 * since it's a bit fragile.
 
843
                 */
 
844
                if (nrels != 0)
 
845
                        elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
 
846
 
 
847
                /* Can't have child XIDs either; AssignTransactionId enforces this */
 
848
                Assert(nchildren == 0);
 
849
 
 
850
                /*
 
851
                 * If we didn't create XLOG entries, we're done here; otherwise we
 
852
                 * should flush those entries the same as a commit record.      (An
 
853
                 * example of a possible record that wouldn't cause an XID to be
 
854
                 * assigned is a sequence advance record due to nextval() --- we want
 
855
                 * to flush that to disk before reporting commit.)
 
856
                 */
 
857
                if (XactLastRecEnd.xrecoff == 0)
 
858
                        goto cleanup;
 
859
        }
 
860
        else
 
861
        {
 
862
                /*
 
863
                 * Begin commit critical section and insert the commit XLOG record.
 
864
                 */
 
865
                XLogRecData rdata[3];
 
866
                int                     lastrdata = 0;
 
867
                xl_xact_commit xlrec;
 
868
 
 
869
                /* Tell bufmgr and smgr to prepare for commit */
 
870
                BufmgrCommit();
 
871
 
 
872
                /*
 
873
                 * Mark ourselves as within our "commit critical section".      This
 
874
                 * forces any concurrent checkpoint to wait until we've updated
 
875
                 * pg_clog.  Without this, it is possible for the checkpoint to set
 
876
                 * REDO after the XLOG record but fail to flush the pg_clog update to
 
877
                 * disk, leading to loss of the transaction commit if the system
 
878
                 * crashes a little later.
 
879
                 *
 
880
                 * Note: we could, but don't bother to, set this flag in
 
881
                 * RecordTransactionAbort.      That's because loss of a transaction abort
 
882
                 * is noncritical; the presumption would be that it aborted, anyway.
 
883
                 *
 
884
                 * It's safe to change the inCommit flag of our own backend without
 
885
                 * holding the ProcArrayLock, since we're the only one modifying it.
 
886
                 * This makes checkpoint's determination of which xacts are inCommit a
 
887
                 * bit fuzzy, but it doesn't matter.
 
888
                 */
 
889
                START_CRIT_SECTION();
 
890
                MyProc->inCommit = true;
 
891
 
 
892
                SetCurrentTransactionStopTimestamp();
 
893
                xlrec.xact_time = xactStopTimestamp;
 
894
                xlrec.nrels = nrels;
 
895
                xlrec.nsubxacts = nchildren;
 
896
                rdata[0].data = (char *) (&xlrec);
 
897
                rdata[0].len = MinSizeOfXactCommit;
 
898
                rdata[0].buffer = InvalidBuffer;
 
899
                /* dump rels to delete */
 
900
                if (nrels > 0)
 
901
                {
 
902
                        rdata[0].next = &(rdata[1]);
 
903
                        rdata[1].data = (char *) rels;
 
904
                        rdata[1].len = nrels * sizeof(RelFileNode);
 
905
                        rdata[1].buffer = InvalidBuffer;
 
906
                        lastrdata = 1;
 
907
                }
 
908
                /* dump committed child Xids */
 
909
                if (nchildren > 0)
 
910
                {
 
911
                        rdata[lastrdata].next = &(rdata[2]);
 
912
                        rdata[2].data = (char *) children;
 
913
                        rdata[2].len = nchildren * sizeof(TransactionId);
 
914
                        rdata[2].buffer = InvalidBuffer;
 
915
                        lastrdata = 2;
 
916
                }
 
917
                rdata[lastrdata].next = NULL;
 
918
 
 
919
                (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
 
920
        }
 
921
 
 
922
        /*
 
923
         * Check if we want to commit asynchronously.  If the user has set
 
924
         * synchronous_commit = off, and we're not doing cleanup of any non-temp
 
925
         * rels nor committing any command that wanted to force sync commit, then
 
926
         * we can defer flushing XLOG.  (We must not allow asynchronous commit if
 
927
         * there are any non-temp tables to be deleted, because we might delete
 
928
         * the files before the COMMIT record is flushed to disk.  We do allow
 
929
         * asynchronous commit if all to-be-deleted tables are temporary though,
 
930
         * since they are lost anyway if we crash.)
 
931
         */
 
932
        if (XactSyncCommit || forceSyncCommit || haveNonTemp)
 
933
        {
 
934
                /*
 
935
                 * Synchronous commit case.
 
936
                 *
 
937
                 * Sleep before flush! So we can flush more than one commit records
 
938
                 * per single fsync.  (The idea is some other backend may do the
 
939
                 * XLogFlush while we're sleeping.  This needs work still, because on
 
940
                 * most Unixen, the minimum select() delay is 10msec or more, which is
 
941
                 * way too long.)
 
942
                 *
 
943
                 * We do not sleep if enableFsync is not turned on, nor if there are
 
944
                 * fewer than CommitSiblings other backends with active transactions.
 
945
                 */
 
946
                if (CommitDelay > 0 && enableFsync &&
 
947
                        CountActiveBackends() >= CommitSiblings)
 
948
                        pg_usleep(CommitDelay);
 
949
 
 
950
                XLogFlush(XactLastRecEnd);
 
951
 
 
952
                /*
 
953
                 * Now we may update the CLOG, if we wrote a COMMIT record above
 
954
                 */
 
955
                if (markXidCommitted)
 
956
                        TransactionIdCommitTree(xid, nchildren, children);
 
957
        }
 
958
        else
 
959
        {
 
960
                /*
 
961
                 * Asynchronous commit case.
 
962
                 *
 
963
                 * Report the latest async commit LSN, so that the WAL writer knows to
 
964
                 * flush this commit.
 
965
                 */
 
966
                XLogSetAsyncCommitLSN(XactLastRecEnd);
 
967
 
 
968
                /*
 
969
                 * We must not immediately update the CLOG, since we didn't flush the
 
970
                 * XLOG. Instead, we store the LSN up to which the XLOG must be
 
971
                 * flushed before the CLOG may be updated.
 
972
                 */
 
973
                if (markXidCommitted)
 
974
                        TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
 
975
        }
 
976
 
 
977
        /*
 
978
         * If we entered a commit critical section, leave it now, and let
 
979
         * checkpoints proceed.
 
980
         */
 
981
        if (markXidCommitted)
 
982
        {
 
983
                MyProc->inCommit = false;
 
984
                END_CRIT_SECTION();
 
985
        }
 
986
 
 
987
        /* Compute latestXid while we have the child XIDs handy */
 
988
        latestXid = TransactionIdLatest(xid, nchildren, children);
 
989
 
 
990
        /* Reset XactLastRecEnd until the next transaction writes something */
 
991
        XactLastRecEnd.xrecoff = 0;
 
992
 
 
993
cleanup:
 
994
        /* Clean up local data */
 
995
        if (rels)
 
996
                pfree(rels);
 
997
 
 
998
        return latestXid;
 
999
}
 
1000
 
 
1001
 
 
1002
/*
 
1003
 *      AtCommit_LocalCache
 
1004
 */
 
1005
static void
 
1006
AtCommit_LocalCache(void)
 
1007
{
 
1008
        /*
 
1009
         * Make catalog changes visible to me for the next command.
 
1010
         */
 
1011
        CommandEndInvalidationMessages();
 
1012
}
 
1013
 
 
1014
/*
 
1015
 *      AtCommit_Memory
 
1016
 */
 
1017
static void
 
1018
AtCommit_Memory(void)
 
1019
{
 
1020
        /*
 
1021
         * Now that we're "out" of a transaction, have the system allocate things
 
1022
         * in the top memory context instead of per-transaction contexts.
 
1023
         */
 
1024
        MemoryContextSwitchTo(TopMemoryContext);
 
1025
 
 
1026
        /*
 
1027
         * Release all transaction-local memory.
 
1028
         */
 
1029
        Assert(TopTransactionContext != NULL);
 
1030
        MemoryContextDelete(TopTransactionContext);
 
1031
        TopTransactionContext = NULL;
 
1032
        CurTransactionContext = NULL;
 
1033
        CurrentTransactionState->curTransactionContext = NULL;
 
1034
}
 
1035
 
 
1036
/* ----------------------------------------------------------------
 
1037
 *                                              CommitSubTransaction stuff
 
1038
 * ----------------------------------------------------------------
 
1039
 */
 
1040
 
 
1041
/*
 
1042
 * AtSubCommit_Memory
 
1043
 */
 
1044
static void
 
1045
AtSubCommit_Memory(void)
 
1046
{
 
1047
        TransactionState s = CurrentTransactionState;
 
1048
 
 
1049
        Assert(s->parent != NULL);
 
1050
 
 
1051
        /* Return to parent transaction level's memory context. */
 
1052
        CurTransactionContext = s->parent->curTransactionContext;
 
1053
        MemoryContextSwitchTo(CurTransactionContext);
 
1054
 
 
1055
        /*
 
1056
         * Ordinarily we cannot throw away the child's CurTransactionContext,
 
1057
         * since the data it contains will be needed at upper commit.  However, if
 
1058
         * there isn't actually anything in it, we can throw it away.  This avoids
 
1059
         * a small memory leak in the common case of "trivial" subxacts.
 
1060
         */
 
1061
        if (MemoryContextIsEmpty(s->curTransactionContext))
 
1062
        {
 
1063
                MemoryContextDelete(s->curTransactionContext);
 
1064
                s->curTransactionContext = NULL;
 
1065
        }
 
1066
}
 
1067
 
 
1068
/*
 
1069
 * AtSubCommit_childXids
 
1070
 *
 
1071
 * Pass my own XID and my child XIDs up to my parent as committed children.
 
1072
 */
 
1073
static void
 
1074
AtSubCommit_childXids(void)
 
1075
{
 
1076
        TransactionState s = CurrentTransactionState;
 
1077
        int                     new_nChildXids;
 
1078
 
 
1079
        Assert(s->parent != NULL);
 
1080
 
 
1081
        /*
 
1082
         * The parent childXids array will need to hold my XID and all my
 
1083
         * childXids, in addition to the XIDs already there.
 
1084
         */
 
1085
        new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
 
1086
 
 
1087
        /* Allocate or enlarge the parent array if necessary */
 
1088
        if (s->parent->maxChildXids < new_nChildXids)
 
1089
        {
 
1090
                int                             new_maxChildXids;
 
1091
                TransactionId  *new_childXids;
 
1092
 
 
1093
                /*
 
1094
                 * Make it 2x what's needed right now, to avoid having to enlarge it
 
1095
                 * repeatedly. But we can't go above MaxAllocSize.  (The latter
 
1096
                 * limit is what ensures that we don't need to worry about integer
 
1097
                 * overflow here or in the calculation of new_nChildXids.)
 
1098
                 */
 
1099
                new_maxChildXids = Min(new_nChildXids * 2,
 
1100
                                                           (int) (MaxAllocSize / sizeof(TransactionId)));
 
1101
 
 
1102
                if (new_maxChildXids < new_nChildXids)
 
1103
                        ereport(ERROR,
 
1104
                                        (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 
1105
                                         errmsg("maximum number of committed subtransactions (%d) exceeded",
 
1106
                                                        (int) (MaxAllocSize / sizeof(TransactionId)))));
 
1107
 
 
1108
                /*
 
1109
                 * We keep the child-XID arrays in TopTransactionContext; this avoids
 
1110
                 * setting up child-transaction contexts for what might be just a few
 
1111
                 * bytes of grandchild XIDs.
 
1112
                 */
 
1113
                if (s->parent->childXids == NULL)
 
1114
                        new_childXids =
 
1115
                                MemoryContextAlloc(TopTransactionContext, 
 
1116
                                                                   new_maxChildXids * sizeof(TransactionId));
 
1117
                else
 
1118
                        new_childXids = repalloc(s->parent->childXids, 
 
1119
                                                                         new_maxChildXids * sizeof(TransactionId));
 
1120
 
 
1121
                s->parent->childXids  = new_childXids;
 
1122
                s->parent->maxChildXids = new_maxChildXids;
 
1123
        }
 
1124
 
 
1125
        /*
 
1126
         * Copy all my XIDs to parent's array.
 
1127
         *
 
1128
         * Note: We rely on the fact that the XID of a child always follows that
 
1129
         * of its parent.  By copying the XID of this subtransaction before the
 
1130
         * XIDs of its children, we ensure that the array stays ordered.  Likewise,
 
1131
         * all XIDs already in the array belong to subtransactions started and
 
1132
         * subcommitted before us, so their XIDs must precede ours.
 
1133
         */
 
1134
        s->parent->childXids[s->parent->nChildXids] = s->transactionId;
 
1135
 
 
1136
        if (s->nChildXids > 0)
 
1137
                memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
 
1138
                           s->childXids,
 
1139
                           s->nChildXids * sizeof(TransactionId));
 
1140
 
 
1141
        s->parent->nChildXids = new_nChildXids;
 
1142
 
 
1143
        /* Release child's array to avoid leakage */
 
1144
        if (s->childXids != NULL)
 
1145
                pfree(s->childXids);
 
1146
        /* We must reset these to avoid double-free if fail later in commit */
 
1147
        s->childXids = NULL;
 
1148
        s->nChildXids = 0;
 
1149
        s->maxChildXids = 0;
 
1150
}
 
1151
 
 
1152
/* ----------------------------------------------------------------
 
1153
 *                                              AbortTransaction stuff
 
1154
 * ----------------------------------------------------------------
 
1155
 */
 
1156
 
 
1157
/*
 
1158
 *      RecordTransactionAbort
 
1159
 *
 
1160
 * Returns latest XID among xact and its children, or InvalidTransactionId
 
1161
 * if the xact has no XID.      (We compute that here just because it's easier.)
 
1162
 */
 
1163
static TransactionId
 
1164
RecordTransactionAbort(bool isSubXact)
 
1165
{
 
1166
        TransactionId xid = GetCurrentTransactionIdIfAny();
 
1167
        TransactionId latestXid;
 
1168
        int                     nrels;
 
1169
        RelFileNode *rels;
 
1170
        int                     nchildren;
 
1171
        TransactionId *children;
 
1172
        XLogRecData rdata[3];
 
1173
        int                     lastrdata = 0;
 
1174
        xl_xact_abort xlrec;
 
1175
 
 
1176
        /*
 
1177
         * If we haven't been assigned an XID, nobody will care whether we aborted
 
1178
         * or not.      Hence, we're done in that case.  It does not matter if we have
 
1179
         * rels to delete (note that this routine is not responsible for actually
 
1180
         * deleting 'em).  We cannot have any child XIDs, either.
 
1181
         */
 
1182
        if (!TransactionIdIsValid(xid))
 
1183
        {
 
1184
                /* Reset XactLastRecEnd until the next transaction writes something */
 
1185
                if (!isSubXact)
 
1186
                        XactLastRecEnd.xrecoff = 0;
 
1187
                return InvalidTransactionId;
 
1188
        }
 
1189
 
 
1190
        /*
 
1191
         * We have a valid XID, so we should write an ABORT record for it.
 
1192
         *
 
1193
         * We do not flush XLOG to disk here, since the default assumption after a
 
1194
         * crash would be that we aborted, anyway.      For the same reason, we don't
 
1195
         * need to worry about interlocking against checkpoint start.
 
1196
         */
 
1197
 
 
1198
        /*
 
1199
         * Check that we haven't aborted halfway through RecordTransactionCommit.
 
1200
         */
 
1201
        if (TransactionIdDidCommit(xid))
 
1202
                elog(PANIC, "cannot abort transaction %u, it was already committed",
 
1203
                         xid);
 
1204
 
 
1205
        /* Fetch the data we need for the abort record */
 
1206
        nrels = smgrGetPendingDeletes(false, &rels, NULL);
 
1207
        nchildren = xactGetCommittedChildren(&children);
 
1208
 
 
1209
        /* XXX do we really need a critical section here? */
 
1210
        START_CRIT_SECTION();
 
1211
 
 
1212
        /* Write the ABORT record */
 
1213
        if (isSubXact)
 
1214
                xlrec.xact_time = GetCurrentTimestamp();
 
1215
        else
 
1216
        {
 
1217
                SetCurrentTransactionStopTimestamp();
 
1218
                xlrec.xact_time = xactStopTimestamp;
 
1219
        }
 
1220
        xlrec.nrels = nrels;
 
1221
        xlrec.nsubxacts = nchildren;
 
1222
        rdata[0].data = (char *) (&xlrec);
 
1223
        rdata[0].len = MinSizeOfXactAbort;
 
1224
        rdata[0].buffer = InvalidBuffer;
 
1225
        /* dump rels to delete */
 
1226
        if (nrels > 0)
 
1227
        {
 
1228
                rdata[0].next = &(rdata[1]);
 
1229
                rdata[1].data = (char *) rels;
 
1230
                rdata[1].len = nrels * sizeof(RelFileNode);
 
1231
                rdata[1].buffer = InvalidBuffer;
 
1232
                lastrdata = 1;
 
1233
        }
 
1234
        /* dump committed child Xids */
 
1235
        if (nchildren > 0)
 
1236
        {
 
1237
                rdata[lastrdata].next = &(rdata[2]);
 
1238
                rdata[2].data = (char *) children;
 
1239
                rdata[2].len = nchildren * sizeof(TransactionId);
 
1240
                rdata[2].buffer = InvalidBuffer;
 
1241
                lastrdata = 2;
 
1242
        }
 
1243
        rdata[lastrdata].next = NULL;
 
1244
 
 
1245
        (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
 
1246
 
 
1247
        /*
 
1248
         * Mark the transaction aborted in clog.  This is not absolutely necessary
 
1249
         * but we may as well do it while we are here; also, in the subxact case
 
1250
         * it is helpful because XactLockTableWait makes use of it to avoid
 
1251
         * waiting for already-aborted subtransactions.  It is OK to do it without
 
1252
         * having flushed the ABORT record to disk, because in event of a crash
 
1253
         * we'd be assumed to have aborted anyway.
 
1254
         */
 
1255
        TransactionIdAbortTree(xid, nchildren, children);
 
1256
 
 
1257
        END_CRIT_SECTION();
 
1258
 
 
1259
        /* Compute latestXid while we have the child XIDs handy */
 
1260
        latestXid = TransactionIdLatest(xid, nchildren, children);
 
1261
 
 
1262
        /*
 
1263
         * If we're aborting a subtransaction, we can immediately remove failed
 
1264
         * XIDs from PGPROC's cache of running child XIDs.  We do that here for
 
1265
         * subxacts, because we already have the child XID array at hand.  For
 
1266
         * main xacts, the equivalent happens just after this function returns.
 
1267
         */
 
1268
        if (isSubXact)
 
1269
                XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
 
1270
 
 
1271
        /* Reset XactLastRecEnd until the next transaction writes something */
 
1272
        if (!isSubXact)
 
1273
                XactLastRecEnd.xrecoff = 0;
 
1274
 
 
1275
        /* And clean up local data */
 
1276
        if (rels)
 
1277
                pfree(rels);
 
1278
 
 
1279
        return latestXid;
 
1280
}
 
1281
 
 
1282
/*
 
1283
 *      AtAbort_Memory
 
1284
 */
 
1285
static void
 
1286
AtAbort_Memory(void)
 
1287
{
 
1288
        /*
 
1289
         * Switch into TransactionAbortContext, which should have some free space
 
1290
         * even if nothing else does.  We'll work in this context until we've
 
1291
         * finished cleaning up.
 
1292
         *
 
1293
         * It is barely possible to get here when we've not been able to create
 
1294
         * TransactionAbortContext yet; if so use TopMemoryContext.
 
1295
         */
 
1296
        if (TransactionAbortContext != NULL)
 
1297
                MemoryContextSwitchTo(TransactionAbortContext);
 
1298
        else
 
1299
                MemoryContextSwitchTo(TopMemoryContext);
 
1300
}
 
1301
 
 
1302
/*
 
1303
 * AtSubAbort_Memory
 
1304
 */
 
1305
static void
 
1306
AtSubAbort_Memory(void)
 
1307
{
 
1308
        Assert(TransactionAbortContext != NULL);
 
1309
 
 
1310
        MemoryContextSwitchTo(TransactionAbortContext);
 
1311
}
 
1312
 
 
1313
 
 
1314
/*
 
1315
 *      AtAbort_ResourceOwner
 
1316
 */
 
1317
static void
 
1318
AtAbort_ResourceOwner(void)
 
1319
{
 
1320
        /*
 
1321
         * Make sure we have a valid ResourceOwner, if possible (else it will be
 
1322
         * NULL, which is OK)
 
1323
         */
 
1324
        CurrentResourceOwner = TopTransactionResourceOwner;
 
1325
}
 
1326
 
 
1327
/*
 
1328
 * AtSubAbort_ResourceOwner
 
1329
 */
 
1330
static void
 
1331
AtSubAbort_ResourceOwner(void)
 
1332
{
 
1333
        TransactionState s = CurrentTransactionState;
 
1334
 
 
1335
        /* Make sure we have a valid ResourceOwner */
 
1336
        CurrentResourceOwner = s->curTransactionOwner;
 
1337
}
 
1338
 
 
1339
 
 
1340
/*
 
1341
 * AtSubAbort_childXids
 
1342
 */
 
1343
static void
 
1344
AtSubAbort_childXids(void)
 
1345
{
 
1346
        TransactionState s = CurrentTransactionState;
 
1347
 
 
1348
        /*
 
1349
         * We keep the child-XID arrays in TopTransactionContext (see
 
1350
         * AtSubCommit_childXids).      This means we'd better free the array
 
1351
         * explicitly at abort to avoid leakage.
 
1352
         */
 
1353
        if (s->childXids != NULL)
 
1354
                pfree(s->childXids);
 
1355
        s->childXids = NULL;
 
1356
        s->nChildXids = 0;
 
1357
        s->maxChildXids = 0;
 
1358
}
 
1359
 
 
1360
/* ----------------------------------------------------------------
 
1361
 *                                              CleanupTransaction stuff
 
1362
 * ----------------------------------------------------------------
 
1363
 */
 
1364
 
 
1365
/*
 
1366
 *      AtCleanup_Memory
 
1367
 */
 
1368
static void
 
1369
AtCleanup_Memory(void)
 
1370
{
 
1371
        Assert(CurrentTransactionState->parent == NULL);
 
1372
 
 
1373
        /*
 
1374
         * Now that we're "out" of a transaction, have the system allocate things
 
1375
         * in the top memory context instead of per-transaction contexts.
 
1376
         */
 
1377
        MemoryContextSwitchTo(TopMemoryContext);
 
1378
 
 
1379
        /*
 
1380
         * Clear the special abort context for next time.
 
1381
         */
 
1382
        if (TransactionAbortContext != NULL)
 
1383
                MemoryContextResetAndDeleteChildren(TransactionAbortContext);
 
1384
 
 
1385
        /*
 
1386
         * Release all transaction-local memory.
 
1387
         */
 
1388
        if (TopTransactionContext != NULL)
 
1389
                MemoryContextDelete(TopTransactionContext);
 
1390
        TopTransactionContext = NULL;
 
1391
        CurTransactionContext = NULL;
 
1392
        CurrentTransactionState->curTransactionContext = NULL;
 
1393
}
 
1394
 
 
1395
 
 
1396
/* ----------------------------------------------------------------
 
1397
 *                                              CleanupSubTransaction stuff
 
1398
 * ----------------------------------------------------------------
 
1399
 */
 
1400
 
 
1401
/*
 
1402
 * AtSubCleanup_Memory
 
1403
 */
 
1404
static void
 
1405
AtSubCleanup_Memory(void)
 
1406
{
 
1407
        TransactionState s = CurrentTransactionState;
 
1408
 
 
1409
        Assert(s->parent != NULL);
 
1410
 
 
1411
        /* Make sure we're not in an about-to-be-deleted context */
 
1412
        MemoryContextSwitchTo(s->parent->curTransactionContext);
 
1413
        CurTransactionContext = s->parent->curTransactionContext;
 
1414
 
 
1415
        /*
 
1416
         * Clear the special abort context for next time.
 
1417
         */
 
1418
        if (TransactionAbortContext != NULL)
 
1419
                MemoryContextResetAndDeleteChildren(TransactionAbortContext);
 
1420
 
 
1421
        /*
 
1422
         * Delete the subxact local memory contexts. Its CurTransactionContext can
 
1423
         * go too (note this also kills CurTransactionContexts from any children
 
1424
         * of the subxact).
 
1425
         */
 
1426
        if (s->curTransactionContext)
 
1427
                MemoryContextDelete(s->curTransactionContext);
 
1428
        s->curTransactionContext = NULL;
 
1429
}
 
1430
 
 
1431
/* ----------------------------------------------------------------
 
1432
 *                                              interface routines
 
1433
 * ----------------------------------------------------------------
 
1434
 */
 
1435
 
 
1436
/*
 
1437
 *      StartTransaction
 
1438
 */
 
1439
static void
 
1440
StartTransaction(void)
 
1441
{
 
1442
        TransactionState s;
 
1443
        VirtualTransactionId vxid;
 
1444
 
 
1445
        /*
 
1446
         * Let's just make sure the state stack is empty
 
1447
         */
 
1448
        s = &TopTransactionStateData;
 
1449
        CurrentTransactionState = s;
 
1450
 
 
1451
        /*
 
1452
         * check the current transaction state
 
1453
         */
 
1454
        if (s->state != TRANS_DEFAULT)
 
1455
                elog(WARNING, "StartTransaction while in %s state",
 
1456
                         TransStateAsString(s->state));
 
1457
 
 
1458
        /*
 
1459
         * set the current transaction state information appropriately during
 
1460
         * start processing
 
1461
         */
 
1462
        s->state = TRANS_START;
 
1463
        s->transactionId = InvalidTransactionId;        /* until assigned */
 
1464
 
 
1465
        /*
 
1466
         * Make sure we've reset xact state variables
 
1467
         */
 
1468
        XactIsoLevel = DefaultXactIsoLevel;
 
1469
        XactReadOnly = DefaultXactReadOnly;
 
1470
        forceSyncCommit = false;
 
1471
        MyXactAccessedTempRel = false;
 
1472
 
 
1473
        /*
 
1474
         * reinitialize within-transaction counters
 
1475
         */
 
1476
        s->subTransactionId = TopSubTransactionId;
 
1477
        currentSubTransactionId = TopSubTransactionId;
 
1478
        currentCommandId = FirstCommandId;
 
1479
        currentCommandIdUsed = false;
 
1480
 
 
1481
        /*
 
1482
         * must initialize resource-management stuff first
 
1483
         */
 
1484
        AtStart_Memory();
 
1485
        AtStart_ResourceOwner();
 
1486
 
 
1487
        /*
 
1488
         * Assign a new LocalTransactionId, and combine it with the backendId to
 
1489
         * form a virtual transaction id.
 
1490
         */
 
1491
        vxid.backendId = MyBackendId;
 
1492
        vxid.localTransactionId = GetNextLocalTransactionId();
 
1493
 
 
1494
        /*
 
1495
         * Lock the virtual transaction id before we announce it in the proc array
 
1496
         */
 
1497
        VirtualXactLockTableInsert(vxid);
 
1498
 
 
1499
        /*
 
1500
         * Advertise it in the proc array.      We assume assignment of
 
1501
         * LocalTransactionID is atomic, and the backendId should be set already.
 
1502
         */
 
1503
        Assert(MyProc->backendId == vxid.backendId);
 
1504
        MyProc->lxid = vxid.localTransactionId;
 
1505
 
 
1506
        TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
 
1507
 
 
1508
        /*
 
1509
         * set transaction_timestamp() (a/k/a now()).  We want this to be the same
 
1510
         * as the first command's statement_timestamp(), so don't do a fresh
 
1511
         * GetCurrentTimestamp() call (which'd be expensive anyway).  Also, mark
 
1512
         * xactStopTimestamp as unset.
 
1513
         */
 
1514
        xactStartTimestamp = stmtStartTimestamp;
 
1515
        xactStopTimestamp = 0;
 
1516
        pgstat_report_xact_timestamp(xactStartTimestamp);
 
1517
 
 
1518
        /*
 
1519
         * initialize current transaction state fields
 
1520
         *
 
1521
         * note: prevXactReadOnly is not used at the outermost level
 
1522
         */
 
1523
        s->nestingLevel = 1;
 
1524
        s->gucNestLevel = 1;
 
1525
        s->childXids = NULL;
 
1526
        s->nChildXids = 0;
 
1527
        s->maxChildXids = 0;
 
1528
        GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
 
1529
        /* SecurityDefinerContext should never be set outside a transaction */
 
1530
        Assert(!s->prevSecDefCxt);
 
1531
 
 
1532
        /*
 
1533
         * initialize other subsystems for new transaction
 
1534
         */
 
1535
        AtStart_GUC();
 
1536
        AtStart_Inval();
 
1537
        AtStart_Cache();
 
1538
        AfterTriggerBeginXact();
 
1539
 
 
1540
        /*
 
1541
         * done with start processing, set current transaction state to "in
 
1542
         * progress"
 
1543
         */
 
1544
        s->state = TRANS_INPROGRESS;
 
1545
 
 
1546
        ShowTransactionState("StartTransaction");
 
1547
}
 
1548
 
 
1549
 
 
1550
/*
 
1551
 *      CommitTransaction
 
1552
 *
 
1553
 * NB: if you change this routine, better look at PrepareTransaction too!
 
1554
 */
 
1555
static void
 
1556
CommitTransaction(void)
 
1557
{
 
1558
        TransactionState s = CurrentTransactionState;
 
1559
        TransactionId latestXid;
 
1560
 
 
1561
        ShowTransactionState("CommitTransaction");
 
1562
 
 
1563
        /*
 
1564
         * check the current transaction state
 
1565
         */
 
1566
        if (s->state != TRANS_INPROGRESS)
 
1567
                elog(WARNING, "CommitTransaction while in %s state",
 
1568
                         TransStateAsString(s->state));
 
1569
        Assert(s->parent == NULL);
 
1570
 
 
1571
        /*
 
1572
         * Do pre-commit processing (most of this stuff requires database access,
 
1573
         * and in fact could still cause an error...)
 
1574
         *
 
1575
         * It is possible for CommitHoldablePortals to invoke functions that queue
 
1576
         * deferred triggers, and it's also possible that triggers create holdable
 
1577
         * cursors.  So we have to loop until there's nothing left to do.
 
1578
         */
 
1579
        for (;;)
 
1580
        {
 
1581
                /*
 
1582
                 * Fire all currently pending deferred triggers.
 
1583
                 */
 
1584
                AfterTriggerFireDeferred();
 
1585
 
 
1586
                /*
 
1587
                 * Convert any open holdable cursors into static portals.  If there
 
1588
                 * weren't any, we are done ... otherwise loop back to check if they
 
1589
                 * queued deferred triggers.  Lather, rinse, repeat.
 
1590
                 */
 
1591
                if (!CommitHoldablePortals())
 
1592
                        break;
 
1593
        }
 
1594
 
 
1595
        /* Now we can shut down the deferred-trigger manager */
 
1596
        AfterTriggerEndXact(true);
 
1597
 
 
1598
        /* Close any open regular cursors */
 
1599
        AtCommit_Portals();
 
1600
 
 
1601
        /*
 
1602
         * Let ON COMMIT management do its thing (must happen after closing
 
1603
         * cursors, to avoid dangling-reference problems)
 
1604
         */
 
1605
        PreCommit_on_commit_actions();
 
1606
 
 
1607
        /* close large objects before lower-level cleanup */
 
1608
        AtEOXact_LargeObject(true);
 
1609
 
 
1610
        /* NOTIFY commit must come before lower-level cleanup */
 
1611
        AtCommit_Notify();
 
1612
 
 
1613
        /*
 
1614
         * Update flat files if we changed pg_database, pg_authid or
 
1615
         * pg_auth_members.  This should be the last step before commit.
 
1616
         */
 
1617
        AtEOXact_UpdateFlatFiles(true);
 
1618
 
 
1619
        /* Prevent cancel/die interrupt while cleaning up */
 
1620
        HOLD_INTERRUPTS();
 
1621
 
 
1622
        /*
 
1623
         * set the current transaction state information appropriately during
 
1624
         * commit processing
 
1625
         */
 
1626
        s->state = TRANS_COMMIT;
 
1627
 
 
1628
        /*
 
1629
         * Here is where we really truly commit.
 
1630
         */
 
1631
        latestXid = RecordTransactionCommit();
 
1632
 
 
1633
        TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
 
1634
 
 
1635
        /*
 
1636
         * Let others know about no transaction in progress by me. Note that this
 
1637
         * must be done _before_ releasing locks we hold and _after_
 
1638
         * RecordTransactionCommit.
 
1639
         */
 
1640
        ProcArrayEndTransaction(MyProc, latestXid);
 
1641
 
 
1642
        /*
 
1643
         * This is all post-commit cleanup.  Note that if an error is raised here,
 
1644
         * it's too late to abort the transaction.  This should be just
 
1645
         * noncritical resource releasing.
 
1646
         *
 
1647
         * The ordering of operations is not entirely random.  The idea is:
 
1648
         * release resources visible to other backends (eg, files, buffer pins);
 
1649
         * then release locks; then release backend-local resources. We want to
 
1650
         * release locks at the point where any backend waiting for us will see
 
1651
         * our transaction as being fully cleaned up.
 
1652
         *
 
1653
         * Resources that can be associated with individual queries are handled by
 
1654
         * the ResourceOwner mechanism.  The other calls here are for backend-wide
 
1655
         * state.
 
1656
         */
 
1657
 
 
1658
        CallXactCallbacks(XACT_EVENT_COMMIT);
 
1659
 
 
1660
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
1661
                                                 RESOURCE_RELEASE_BEFORE_LOCKS,
 
1662
                                                 true, true);
 
1663
 
 
1664
        /* Check we've released all buffer pins */
 
1665
        AtEOXact_Buffers(true);
 
1666
 
 
1667
        /* Clean up the relation cache */
 
1668
        AtEOXact_RelationCache(true);
 
1669
 
 
1670
        /* Clean up the snapshot manager */
 
1671
        AtEarlyCommit_Snapshot();
 
1672
 
 
1673
        /*
 
1674
         * Make catalog changes visible to all backends.  This has to happen after
 
1675
         * relcache references are dropped (see comments for
 
1676
         * AtEOXact_RelationCache), but before locks are released (if anyone is
 
1677
         * waiting for lock on a relation we've modified, we want them to know
 
1678
         * about the catalog change before they start using the relation).
 
1679
         */
 
1680
        AtEOXact_Inval(true);
 
1681
 
 
1682
        /*
 
1683
         * Likewise, dropping of files deleted during the transaction is best done
 
1684
         * after releasing relcache and buffer pins.  (This is not strictly
 
1685
         * necessary during commit, since such pins should have been released
 
1686
         * already, but this ordering is definitely critical during abort.)
 
1687
         */
 
1688
        smgrDoPendingDeletes(true);
 
1689
 
 
1690
        AtEOXact_MultiXact();
 
1691
 
 
1692
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
1693
                                                 RESOURCE_RELEASE_LOCKS,
 
1694
                                                 true, true);
 
1695
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
1696
                                                 RESOURCE_RELEASE_AFTER_LOCKS,
 
1697
                                                 true, true);
 
1698
 
 
1699
        /* Check we've released all catcache entries */
 
1700
        AtEOXact_CatCache(true);
 
1701
 
 
1702
        AtEOXact_GUC(true, 1);
 
1703
        AtEOXact_SPI(true);
 
1704
        AtEOXact_xml();
 
1705
        AtEOXact_on_commit_actions(true);
 
1706
        AtEOXact_Namespace(true);
 
1707
        /* smgrcommit already done */
 
1708
        AtEOXact_Files();
 
1709
        AtEOXact_ComboCid();
 
1710
        AtEOXact_HashTables(true);
 
1711
        AtEOXact_PgStat(true);
 
1712
        AtEOXact_Snapshot(true);
 
1713
        pgstat_report_xact_timestamp(0);
 
1714
 
 
1715
        CurrentResourceOwner = NULL;
 
1716
        ResourceOwnerDelete(TopTransactionResourceOwner);
 
1717
        s->curTransactionOwner = NULL;
 
1718
        CurTransactionResourceOwner = NULL;
 
1719
        TopTransactionResourceOwner = NULL;
 
1720
 
 
1721
        AtCommit_Memory();
 
1722
 
 
1723
        s->transactionId = InvalidTransactionId;
 
1724
        s->subTransactionId = InvalidSubTransactionId;
 
1725
        s->nestingLevel = 0;
 
1726
        s->gucNestLevel = 0;
 
1727
        s->childXids = NULL;
 
1728
        s->nChildXids = 0;
 
1729
        s->maxChildXids = 0;
 
1730
 
 
1731
        /*
 
1732
         * done with commit processing, set current transaction state back to
 
1733
         * default
 
1734
         */
 
1735
        s->state = TRANS_DEFAULT;
 
1736
 
 
1737
        RESUME_INTERRUPTS();
 
1738
}
 
1739
 
 
1740
 
 
1741
/*
 
1742
 *      PrepareTransaction
 
1743
 *
 
1744
 * NB: if you change this routine, better look at CommitTransaction too!
 
1745
 */
 
1746
static void
 
1747
PrepareTransaction(void)
 
1748
{
 
1749
        TransactionState s = CurrentTransactionState;
 
1750
        TransactionId xid = GetCurrentTransactionId();
 
1751
        GlobalTransaction gxact;
 
1752
        TimestampTz prepared_at;
 
1753
 
 
1754
        ShowTransactionState("PrepareTransaction");
 
1755
 
 
1756
        /*
 
1757
         * check the current transaction state
 
1758
         */
 
1759
        if (s->state != TRANS_INPROGRESS)
 
1760
                elog(WARNING, "PrepareTransaction while in %s state",
 
1761
                         TransStateAsString(s->state));
 
1762
        Assert(s->parent == NULL);
 
1763
 
 
1764
        /*
 
1765
         * Do pre-commit processing (most of this stuff requires database access,
 
1766
         * and in fact could still cause an error...)
 
1767
         *
 
1768
         * It is possible for PrepareHoldablePortals to invoke functions that
 
1769
         * queue deferred triggers, and it's also possible that triggers create
 
1770
         * holdable cursors.  So we have to loop until there's nothing left to do.
 
1771
         */
 
1772
        for (;;)
 
1773
        {
 
1774
                /*
 
1775
                 * Fire all currently pending deferred triggers.
 
1776
                 */
 
1777
                AfterTriggerFireDeferred();
 
1778
 
 
1779
                /*
 
1780
                 * Convert any open holdable cursors into static portals.  If there
 
1781
                 * weren't any, we are done ... otherwise loop back to check if they
 
1782
                 * queued deferred triggers.  Lather, rinse, repeat.
 
1783
                 */
 
1784
                if (!PrepareHoldablePortals())
 
1785
                        break;
 
1786
        }
 
1787
 
 
1788
        /* Now we can shut down the deferred-trigger manager */
 
1789
        AfterTriggerEndXact(true);
 
1790
 
 
1791
        /* Close any open regular cursors */
 
1792
        AtCommit_Portals();
 
1793
 
 
1794
        /*
 
1795
         * Let ON COMMIT management do its thing (must happen after closing
 
1796
         * cursors, to avoid dangling-reference problems)
 
1797
         */
 
1798
        PreCommit_on_commit_actions();
 
1799
 
 
1800
        /* close large objects before lower-level cleanup */
 
1801
        AtEOXact_LargeObject(true);
 
1802
 
 
1803
        /* NOTIFY and flatfiles will be handled below */
 
1804
 
 
1805
        /*
 
1806
         * Don't allow PREPARE TRANSACTION if we've accessed a temporary table
 
1807
         * in this transaction.  Having the prepared xact hold locks on another
 
1808
         * backend's temp table seems a bad idea --- for instance it would prevent
 
1809
         * the backend from exiting.  There are other problems too, such as how
 
1810
         * to clean up the source backend's local buffers and ON COMMIT state
 
1811
         * if the prepared xact includes a DROP of a temp table.
 
1812
         *
 
1813
         * We must check this after executing any ON COMMIT actions, because
 
1814
         * they might still access a temp relation.
 
1815
         *
 
1816
         * XXX In principle this could be relaxed to allow some useful special
 
1817
         * cases, such as a temp table created and dropped all within the
 
1818
         * transaction.  That seems to require much more bookkeeping though.
 
1819
         */
 
1820
        if (MyXactAccessedTempRel)
 
1821
                ereport(ERROR,
 
1822
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
1823
                                 errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
 
1824
 
 
1825
        /* Prevent cancel/die interrupt while cleaning up */
 
1826
        HOLD_INTERRUPTS();
 
1827
 
 
1828
        /*
 
1829
         * set the current transaction state information appropriately during
 
1830
         * prepare processing
 
1831
         */
 
1832
        s->state = TRANS_PREPARE;
 
1833
 
 
1834
        prepared_at = GetCurrentTimestamp();
 
1835
 
 
1836
        /* Tell bufmgr and smgr to prepare for commit */
 
1837
        BufmgrCommit();
 
1838
 
 
1839
        /*
 
1840
         * Reserve the GID for this transaction. This could fail if the requested
 
1841
         * GID is invalid or already in use.
 
1842
         */
 
1843
        gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
 
1844
                                                        GetUserId(), MyDatabaseId);
 
1845
        prepareGID = NULL;
 
1846
 
 
1847
        /*
 
1848
         * Collect data for the 2PC state file.  Note that in general, no actual
 
1849
         * state change should happen in the called modules during this step,
 
1850
         * since it's still possible to fail before commit, and in that case we
 
1851
         * want transaction abort to be able to clean up.  (In particular, the
 
1852
         * AtPrepare routines may error out if they find cases they cannot
 
1853
         * handle.)  State cleanup should happen in the PostPrepare routines
 
1854
         * below.  However, some modules can go ahead and clear state here because
 
1855
         * they wouldn't do anything with it during abort anyway.
 
1856
         *
 
1857
         * Note: because the 2PC state file records will be replayed in the same
 
1858
         * order they are made, the order of these calls has to match the order in
 
1859
         * which we want things to happen during COMMIT PREPARED or ROLLBACK
 
1860
         * PREPARED; in particular, pay attention to whether things should happen
 
1861
         * before or after releasing the transaction's locks.
 
1862
         */
 
1863
        StartPrepare(gxact);
 
1864
 
 
1865
        AtPrepare_Notify();
 
1866
        AtPrepare_UpdateFlatFiles();
 
1867
        AtPrepare_Inval();
 
1868
        AtPrepare_Locks();
 
1869
        AtPrepare_PgStat();
 
1870
 
 
1871
        /*
 
1872
         * Here is where we really truly prepare.
 
1873
         *
 
1874
         * We have to record transaction prepares even if we didn't make any
 
1875
         * updates, because the transaction manager might get confused if we lose
 
1876
         * a global transaction.
 
1877
         */
 
1878
        EndPrepare(gxact);
 
1879
 
 
1880
        /*
 
1881
         * Now we clean up backend-internal state and release internal resources.
 
1882
         */
 
1883
 
 
1884
        /* Reset XactLastRecEnd until the next transaction writes something */
 
1885
        XactLastRecEnd.xrecoff = 0;
 
1886
 
 
1887
        /*
 
1888
         * Let others know about no transaction in progress by me.      This has to be
 
1889
         * done *after* the prepared transaction has been marked valid, else
 
1890
         * someone may think it is unlocked and recyclable.
 
1891
         */
 
1892
        ProcArrayClearTransaction(MyProc);
 
1893
 
 
1894
        /*
 
1895
         * This is all post-transaction cleanup.  Note that if an error is raised
 
1896
         * here, it's too late to abort the transaction.  This should be just
 
1897
         * noncritical resource releasing.      See notes in CommitTransaction.
 
1898
         */
 
1899
 
 
1900
        CallXactCallbacks(XACT_EVENT_PREPARE);
 
1901
 
 
1902
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
1903
                                                 RESOURCE_RELEASE_BEFORE_LOCKS,
 
1904
                                                 true, true);
 
1905
 
 
1906
        /* Check we've released all buffer pins */
 
1907
        AtEOXact_Buffers(true);
 
1908
 
 
1909
        /* Clean up the relation cache */
 
1910
        AtEOXact_RelationCache(true);
 
1911
 
 
1912
        /* Clean up the snapshot manager */
 
1913
        AtEarlyCommit_Snapshot();
 
1914
 
 
1915
        /* notify and flatfiles don't need a postprepare call */
 
1916
 
 
1917
        PostPrepare_PgStat();
 
1918
 
 
1919
        PostPrepare_Inval();
 
1920
 
 
1921
        PostPrepare_smgr();
 
1922
 
 
1923
        AtEOXact_MultiXact();
 
1924
 
 
1925
        PostPrepare_Locks(xid);
 
1926
 
 
1927
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
1928
                                                 RESOURCE_RELEASE_LOCKS,
 
1929
                                                 true, true);
 
1930
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
1931
                                                 RESOURCE_RELEASE_AFTER_LOCKS,
 
1932
                                                 true, true);
 
1933
 
 
1934
        /* Check we've released all catcache entries */
 
1935
        AtEOXact_CatCache(true);
 
1936
 
 
1937
        /* PREPARE acts the same as COMMIT as far as GUC is concerned */
 
1938
        AtEOXact_GUC(true, 1);
 
1939
        AtEOXact_SPI(true);
 
1940
        AtEOXact_xml();
 
1941
        AtEOXact_on_commit_actions(true);
 
1942
        AtEOXact_Namespace(true);
 
1943
        /* smgrcommit already done */
 
1944
        AtEOXact_Files();
 
1945
        AtEOXact_ComboCid();
 
1946
        AtEOXact_HashTables(true);
 
1947
        /* don't call AtEOXact_PgStat here */
 
1948
        AtEOXact_Snapshot(true);
 
1949
 
 
1950
        CurrentResourceOwner = NULL;
 
1951
        ResourceOwnerDelete(TopTransactionResourceOwner);
 
1952
        s->curTransactionOwner = NULL;
 
1953
        CurTransactionResourceOwner = NULL;
 
1954
        TopTransactionResourceOwner = NULL;
 
1955
 
 
1956
        AtCommit_Memory();
 
1957
 
 
1958
        s->transactionId = InvalidTransactionId;
 
1959
        s->subTransactionId = InvalidSubTransactionId;
 
1960
        s->nestingLevel = 0;
 
1961
        s->gucNestLevel = 0;
 
1962
        s->childXids = NULL;
 
1963
        s->nChildXids = 0;
 
1964
        s->maxChildXids = 0;
 
1965
 
 
1966
        /*
 
1967
         * done with 1st phase commit processing, set current transaction state
 
1968
         * back to default
 
1969
         */
 
1970
        s->state = TRANS_DEFAULT;
 
1971
 
 
1972
        RESUME_INTERRUPTS();
 
1973
}
 
1974
 
 
1975
 
 
1976
/*
 
1977
 *      AbortTransaction
 
1978
 */
 
1979
static void
 
1980
AbortTransaction(void)
 
1981
{
 
1982
        TransactionState s = CurrentTransactionState;
 
1983
        TransactionId latestXid;
 
1984
 
 
1985
        /* Prevent cancel/die interrupt while cleaning up */
 
1986
        HOLD_INTERRUPTS();
 
1987
 
 
1988
        /* Make sure we have a valid memory context and resource owner */
 
1989
        AtAbort_Memory();
 
1990
        AtAbort_ResourceOwner();
 
1991
 
 
1992
        /*
 
1993
         * Release any LW locks we might be holding as quickly as possible.
 
1994
         * (Regular locks, however, must be held till we finish aborting.)
 
1995
         * Releasing LW locks is critical since we might try to grab them again
 
1996
         * while cleaning up!
 
1997
         */
 
1998
        LWLockReleaseAll();
 
1999
 
 
2000
        /* Clean up buffer I/O and buffer context locks, too */
 
2001
        AbortBufferIO();
 
2002
        UnlockBuffers();
 
2003
 
 
2004
        /*
 
2005
         * Also clean up any open wait for lock, since the lock manager will choke
 
2006
         * if we try to wait for another lock before doing this.
 
2007
         */
 
2008
        LockWaitCancel();
 
2009
 
 
2010
        /*
 
2011
         * check the current transaction state
 
2012
         */
 
2013
        if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
 
2014
                elog(WARNING, "AbortTransaction while in %s state",
 
2015
                         TransStateAsString(s->state));
 
2016
        Assert(s->parent == NULL);
 
2017
 
 
2018
        /*
 
2019
         * set the current transaction state information appropriately during the
 
2020
         * abort processing
 
2021
         */
 
2022
        s->state = TRANS_ABORT;
 
2023
 
 
2024
        /*
 
2025
         * Reset user ID which might have been changed transiently.  We need this
 
2026
         * to clean up in case control escaped out of a SECURITY DEFINER function
 
2027
         * or other local change of CurrentUserId; therefore, the prior value
 
2028
         * of SecurityDefinerContext also needs to be restored.
 
2029
         *
 
2030
         * (Note: it is not necessary to restore session authorization or role
 
2031
         * settings here because those can only be changed via GUC, and GUC will
 
2032
         * take care of rolling them back if need be.)
 
2033
         */
 
2034
        SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
 
2035
 
 
2036
        /*
 
2037
         * do abort processing
 
2038
         */
 
2039
        AfterTriggerEndXact(false);
 
2040
        AtAbort_Portals();
 
2041
        AtEOXact_LargeObject(false);    /* 'false' means it's abort */
 
2042
        AtAbort_Notify();
 
2043
        AtEOXact_UpdateFlatFiles(false);
 
2044
 
 
2045
        /*
 
2046
         * Advertise the fact that we aborted in pg_clog (assuming that we got as
 
2047
         * far as assigning an XID to advertise).
 
2048
         */
 
2049
        latestXid = RecordTransactionAbort(false);
 
2050
 
 
2051
        TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->lxid);
 
2052
 
 
2053
        /*
 
2054
         * Let others know about no transaction in progress by me. Note that this
 
2055
         * must be done _before_ releasing locks we hold and _after_
 
2056
         * RecordTransactionAbort.
 
2057
         */
 
2058
        ProcArrayEndTransaction(MyProc, latestXid);
 
2059
 
 
2060
        /*
 
2061
         * Post-abort cleanup.  See notes in CommitTransaction() concerning
 
2062
         * ordering.
 
2063
         */
 
2064
 
 
2065
        CallXactCallbacks(XACT_EVENT_ABORT);
 
2066
 
 
2067
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
2068
                                                 RESOURCE_RELEASE_BEFORE_LOCKS,
 
2069
                                                 false, true);
 
2070
        AtEOXact_Buffers(false);
 
2071
        AtEOXact_RelationCache(false);
 
2072
        AtEOXact_Inval(false);
 
2073
        smgrDoPendingDeletes(false);
 
2074
        AtEOXact_MultiXact();
 
2075
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
2076
                                                 RESOURCE_RELEASE_LOCKS,
 
2077
                                                 false, true);
 
2078
        ResourceOwnerRelease(TopTransactionResourceOwner,
 
2079
                                                 RESOURCE_RELEASE_AFTER_LOCKS,
 
2080
                                                 false, true);
 
2081
        AtEOXact_CatCache(false);
 
2082
 
 
2083
        AtEOXact_GUC(false, 1);
 
2084
        AtEOXact_SPI(false);
 
2085
        AtEOXact_xml();
 
2086
        AtEOXact_on_commit_actions(false);
 
2087
        AtEOXact_Namespace(false);
 
2088
        AtEOXact_Files();
 
2089
        AtEOXact_ComboCid();
 
2090
        AtEOXact_HashTables(false);
 
2091
        AtEOXact_PgStat(false);
 
2092
        AtEOXact_Snapshot(false);
 
2093
        pgstat_report_xact_timestamp(0);
 
2094
 
 
2095
        /*
 
2096
         * State remains TRANS_ABORT until CleanupTransaction().
 
2097
         */
 
2098
        RESUME_INTERRUPTS();
 
2099
}
 
2100
 
 
2101
/*
 
2102
 *      CleanupTransaction
 
2103
 */
 
2104
static void
 
2105
CleanupTransaction(void)
 
2106
{
 
2107
        TransactionState s = CurrentTransactionState;
 
2108
 
 
2109
        /*
 
2110
         * State should still be TRANS_ABORT from AbortTransaction().
 
2111
         */
 
2112
        if (s->state != TRANS_ABORT)
 
2113
                elog(FATAL, "CleanupTransaction: unexpected state %s",
 
2114
                         TransStateAsString(s->state));
 
2115
 
 
2116
        /*
 
2117
         * do abort cleanup processing
 
2118
         */
 
2119
        AtCleanup_Portals();            /* now safe to release portal memory */
 
2120
 
 
2121
        CurrentResourceOwner = NULL;    /* and resource owner */
 
2122
        if (TopTransactionResourceOwner)
 
2123
                ResourceOwnerDelete(TopTransactionResourceOwner);
 
2124
        s->curTransactionOwner = NULL;
 
2125
        CurTransactionResourceOwner = NULL;
 
2126
        TopTransactionResourceOwner = NULL;
 
2127
 
 
2128
        AtCleanup_Memory();                     /* and transaction memory */
 
2129
 
 
2130
        s->transactionId = InvalidTransactionId;
 
2131
        s->subTransactionId = InvalidSubTransactionId;
 
2132
        s->nestingLevel = 0;
 
2133
        s->gucNestLevel = 0;
 
2134
        s->childXids = NULL;
 
2135
        s->nChildXids = 0;
 
2136
        s->maxChildXids = 0;
 
2137
 
 
2138
        /*
 
2139
         * done with abort processing, set current transaction state back to
 
2140
         * default
 
2141
         */
 
2142
        s->state = TRANS_DEFAULT;
 
2143
}
 
2144
 
 
2145
/*
 
2146
 *      StartTransactionCommand
 
2147
 */
 
2148
void
 
2149
StartTransactionCommand(void)
 
2150
{
 
2151
        TransactionState s = CurrentTransactionState;
 
2152
 
 
2153
        switch (s->blockState)
 
2154
        {
 
2155
                        /*
 
2156
                         * if we aren't in a transaction block, we just do our usual start
 
2157
                         * transaction.
 
2158
                         */
 
2159
                case TBLOCK_DEFAULT:
 
2160
                        StartTransaction();
 
2161
                        s->blockState = TBLOCK_STARTED;
 
2162
                        break;
 
2163
 
 
2164
                        /*
 
2165
                         * We are somewhere in a transaction block or subtransaction and
 
2166
                         * about to start a new command.  For now we do nothing, but
 
2167
                         * someday we may do command-local resource initialization. (Note
 
2168
                         * that any needed CommandCounterIncrement was done by the
 
2169
                         * previous CommitTransactionCommand.)
 
2170
                         */
 
2171
                case TBLOCK_INPROGRESS:
 
2172
                case TBLOCK_SUBINPROGRESS:
 
2173
                        break;
 
2174
 
 
2175
                        /*
 
2176
                         * Here we are in a failed transaction block (one of the commands
 
2177
                         * caused an abort) so we do nothing but remain in the abort
 
2178
                         * state.  Eventually we will get a ROLLBACK command which will
 
2179
                         * get us out of this state.  (It is up to other code to ensure
 
2180
                         * that no commands other than ROLLBACK will be processed in these
 
2181
                         * states.)
 
2182
                         */
 
2183
                case TBLOCK_ABORT:
 
2184
                case TBLOCK_SUBABORT:
 
2185
                        break;
 
2186
 
 
2187
                        /* These cases are invalid. */
 
2188
                case TBLOCK_STARTED:
 
2189
                case TBLOCK_BEGIN:
 
2190
                case TBLOCK_SUBBEGIN:
 
2191
                case TBLOCK_END:
 
2192
                case TBLOCK_SUBEND:
 
2193
                case TBLOCK_ABORT_END:
 
2194
                case TBLOCK_SUBABORT_END:
 
2195
                case TBLOCK_ABORT_PENDING:
 
2196
                case TBLOCK_SUBABORT_PENDING:
 
2197
                case TBLOCK_SUBRESTART:
 
2198
                case TBLOCK_SUBABORT_RESTART:
 
2199
                case TBLOCK_PREPARE:
 
2200
                        elog(ERROR, "StartTransactionCommand: unexpected state %s",
 
2201
                                 BlockStateAsString(s->blockState));
 
2202
                        break;
 
2203
        }
 
2204
 
 
2205
        /*
 
2206
         * We must switch to CurTransactionContext before returning. This is
 
2207
         * already done if we called StartTransaction, otherwise not.
 
2208
         */
 
2209
        Assert(CurTransactionContext != NULL);
 
2210
        MemoryContextSwitchTo(CurTransactionContext);
 
2211
}
 
2212
 
 
2213
/*
 
2214
 *      CommitTransactionCommand
 
2215
 */
 
2216
void
 
2217
CommitTransactionCommand(void)
 
2218
{
 
2219
        TransactionState s = CurrentTransactionState;
 
2220
 
 
2221
        switch (s->blockState)
 
2222
        {
 
2223
                        /*
 
2224
                         * This shouldn't happen, because it means the previous
 
2225
                         * StartTransactionCommand didn't set the STARTED state
 
2226
                         * appropriately.
 
2227
                         */
 
2228
                case TBLOCK_DEFAULT:
 
2229
                        elog(FATAL, "CommitTransactionCommand: unexpected state %s",
 
2230
                                 BlockStateAsString(s->blockState));
 
2231
                        break;
 
2232
 
 
2233
                        /*
 
2234
                         * If we aren't in a transaction block, just do our usual
 
2235
                         * transaction commit, and return to the idle state.
 
2236
                         */
 
2237
                case TBLOCK_STARTED:
 
2238
                        CommitTransaction();
 
2239
                        s->blockState = TBLOCK_DEFAULT;
 
2240
                        break;
 
2241
 
 
2242
                        /*
 
2243
                         * We are completing a "BEGIN TRANSACTION" command, so we change
 
2244
                         * to the "transaction block in progress" state and return.  (We
 
2245
                         * assume the BEGIN did nothing to the database, so we need no
 
2246
                         * CommandCounterIncrement.)
 
2247
                         */
 
2248
                case TBLOCK_BEGIN:
 
2249
                        s->blockState = TBLOCK_INPROGRESS;
 
2250
                        break;
 
2251
 
 
2252
                        /*
 
2253
                         * This is the case when we have finished executing a command
 
2254
                         * someplace within a transaction block.  We increment the command
 
2255
                         * counter and return.
 
2256
                         */
 
2257
                case TBLOCK_INPROGRESS:
 
2258
                case TBLOCK_SUBINPROGRESS:
 
2259
                        CommandCounterIncrement();
 
2260
                        break;
 
2261
 
 
2262
                        /*
 
2263
                         * We are completing a "COMMIT" command.  Do it and return to the
 
2264
                         * idle state.
 
2265
                         */
 
2266
                case TBLOCK_END:
 
2267
                        CommitTransaction();
 
2268
                        s->blockState = TBLOCK_DEFAULT;
 
2269
                        break;
 
2270
 
 
2271
                        /*
 
2272
                         * Here we are in the middle of a transaction block but one of the
 
2273
                         * commands caused an abort so we do nothing but remain in the
 
2274
                         * abort state.  Eventually we will get a ROLLBACK comand.
 
2275
                         */
 
2276
                case TBLOCK_ABORT:
 
2277
                case TBLOCK_SUBABORT:
 
2278
                        break;
 
2279
 
 
2280
                        /*
 
2281
                         * Here we were in an aborted transaction block and we just got
 
2282
                         * the ROLLBACK command from the user, so clean up the
 
2283
                         * already-aborted transaction and return to the idle state.
 
2284
                         */
 
2285
                case TBLOCK_ABORT_END:
 
2286
                        CleanupTransaction();
 
2287
                        s->blockState = TBLOCK_DEFAULT;
 
2288
                        break;
 
2289
 
 
2290
                        /*
 
2291
                         * Here we were in a perfectly good transaction block but the user
 
2292
                         * told us to ROLLBACK anyway.  We have to abort the transaction
 
2293
                         * and then clean up.
 
2294
                         */
 
2295
                case TBLOCK_ABORT_PENDING:
 
2296
                        AbortTransaction();
 
2297
                        CleanupTransaction();
 
2298
                        s->blockState = TBLOCK_DEFAULT;
 
2299
                        break;
 
2300
 
 
2301
                        /*
 
2302
                         * We are completing a "PREPARE TRANSACTION" command.  Do it and
 
2303
                         * return to the idle state.
 
2304
                         */
 
2305
                case TBLOCK_PREPARE:
 
2306
                        PrepareTransaction();
 
2307
                        s->blockState = TBLOCK_DEFAULT;
 
2308
                        break;
 
2309
 
 
2310
                        /*
 
2311
                         * We were just issued a SAVEPOINT inside a transaction block.
 
2312
                         * Start a subtransaction.      (DefineSavepoint already did
 
2313
                         * PushTransaction, so as to have someplace to put the SUBBEGIN
 
2314
                         * state.)
 
2315
                         */
 
2316
                case TBLOCK_SUBBEGIN:
 
2317
                        StartSubTransaction();
 
2318
                        s->blockState = TBLOCK_SUBINPROGRESS;
 
2319
                        break;
 
2320
 
 
2321
                        /*
 
2322
                         * We were issued a COMMIT or RELEASE command, so we end the
 
2323
                         * current subtransaction and return to the parent transaction.
 
2324
                         * The parent might be ended too, so repeat till we are all the
 
2325
                         * way out or find an INPROGRESS transaction.
 
2326
                         */
 
2327
                case TBLOCK_SUBEND:
 
2328
                        do
 
2329
                        {
 
2330
                                CommitSubTransaction();
 
2331
                                s = CurrentTransactionState;    /* changed by pop */
 
2332
                        } while (s->blockState == TBLOCK_SUBEND);
 
2333
                        /* If we had a COMMIT command, finish off the main xact too */
 
2334
                        if (s->blockState == TBLOCK_END)
 
2335
                        {
 
2336
                                Assert(s->parent == NULL);
 
2337
                                CommitTransaction();
 
2338
                                s->blockState = TBLOCK_DEFAULT;
 
2339
                        }
 
2340
                        else if (s->blockState == TBLOCK_PREPARE)
 
2341
                        {
 
2342
                                Assert(s->parent == NULL);
 
2343
                                PrepareTransaction();
 
2344
                                s->blockState = TBLOCK_DEFAULT;
 
2345
                        }
 
2346
                        else
 
2347
                        {
 
2348
                                Assert(s->blockState == TBLOCK_INPROGRESS ||
 
2349
                                           s->blockState == TBLOCK_SUBINPROGRESS);
 
2350
                        }
 
2351
                        break;
 
2352
 
 
2353
                        /*
 
2354
                         * The current already-failed subtransaction is ending due to a
 
2355
                         * ROLLBACK or ROLLBACK TO command, so pop it and recursively
 
2356
                         * examine the parent (which could be in any of several states).
 
2357
                         */
 
2358
                case TBLOCK_SUBABORT_END:
 
2359
                        CleanupSubTransaction();
 
2360
                        CommitTransactionCommand();
 
2361
                        break;
 
2362
 
 
2363
                        /*
 
2364
                         * As above, but it's not dead yet, so abort first.
 
2365
                         */
 
2366
                case TBLOCK_SUBABORT_PENDING:
 
2367
                        AbortSubTransaction();
 
2368
                        CleanupSubTransaction();
 
2369
                        CommitTransactionCommand();
 
2370
                        break;
 
2371
 
 
2372
                        /*
 
2373
                         * The current subtransaction is the target of a ROLLBACK TO
 
2374
                         * command.  Abort and pop it, then start a new subtransaction
 
2375
                         * with the same name.
 
2376
                         */
 
2377
                case TBLOCK_SUBRESTART:
 
2378
                        {
 
2379
                                char       *name;
 
2380
                                int                     savepointLevel;
 
2381
 
 
2382
                                /* save name and keep Cleanup from freeing it */
 
2383
                                name = s->name;
 
2384
                                s->name = NULL;
 
2385
                                savepointLevel = s->savepointLevel;
 
2386
 
 
2387
                                AbortSubTransaction();
 
2388
                                CleanupSubTransaction();
 
2389
 
 
2390
                                DefineSavepoint(NULL);
 
2391
                                s = CurrentTransactionState;    /* changed by push */
 
2392
                                s->name = name;
 
2393
                                s->savepointLevel = savepointLevel;
 
2394
 
 
2395
                                /* This is the same as TBLOCK_SUBBEGIN case */
 
2396
                                AssertState(s->blockState == TBLOCK_SUBBEGIN);
 
2397
                                StartSubTransaction();
 
2398
                                s->blockState = TBLOCK_SUBINPROGRESS;
 
2399
                        }
 
2400
                        break;
 
2401
 
 
2402
                        /*
 
2403
                         * Same as above, but the subtransaction had already failed, so we
 
2404
                         * don't need AbortSubTransaction.
 
2405
                         */
 
2406
                case TBLOCK_SUBABORT_RESTART:
 
2407
                        {
 
2408
                                char       *name;
 
2409
                                int                     savepointLevel;
 
2410
 
 
2411
                                /* save name and keep Cleanup from freeing it */
 
2412
                                name = s->name;
 
2413
                                s->name = NULL;
 
2414
                                savepointLevel = s->savepointLevel;
 
2415
 
 
2416
                                CleanupSubTransaction();
 
2417
 
 
2418
                                DefineSavepoint(NULL);
 
2419
                                s = CurrentTransactionState;    /* changed by push */
 
2420
                                s->name = name;
 
2421
                                s->savepointLevel = savepointLevel;
 
2422
 
 
2423
                                /* This is the same as TBLOCK_SUBBEGIN case */
 
2424
                                AssertState(s->blockState == TBLOCK_SUBBEGIN);
 
2425
                                StartSubTransaction();
 
2426
                                s->blockState = TBLOCK_SUBINPROGRESS;
 
2427
                        }
 
2428
                        break;
 
2429
        }
 
2430
}
 
2431
 
 
2432
/*
 
2433
 *      AbortCurrentTransaction
 
2434
 */
 
2435
void
 
2436
AbortCurrentTransaction(void)
 
2437
{
 
2438
        TransactionState s = CurrentTransactionState;
 
2439
 
 
2440
        switch (s->blockState)
 
2441
        {
 
2442
                case TBLOCK_DEFAULT:
 
2443
                        if (s->state == TRANS_DEFAULT)
 
2444
                        {
 
2445
                                /* we are idle, so nothing to do */
 
2446
                        }
 
2447
                        else
 
2448
                        {
 
2449
                                /*
 
2450
                                 * We can get here after an error during transaction start
 
2451
                                 * (state will be TRANS_START).  Need to clean up the
 
2452
                                 * incompletely started transaction.  First, adjust the
 
2453
                                 * low-level state to suppress warning message from
 
2454
                                 * AbortTransaction.
 
2455
                                 */
 
2456
                                if (s->state == TRANS_START)
 
2457
                                        s->state = TRANS_INPROGRESS;
 
2458
                                AbortTransaction();
 
2459
                                CleanupTransaction();
 
2460
                        }
 
2461
                        break;
 
2462
 
 
2463
                        /*
 
2464
                         * if we aren't in a transaction block, we just do the basic abort
 
2465
                         * & cleanup transaction.
 
2466
                         */
 
2467
                case TBLOCK_STARTED:
 
2468
                        AbortTransaction();
 
2469
                        CleanupTransaction();
 
2470
                        s->blockState = TBLOCK_DEFAULT;
 
2471
                        break;
 
2472
 
 
2473
                        /*
 
2474
                         * If we are in TBLOCK_BEGIN it means something screwed up right
 
2475
                         * after reading "BEGIN TRANSACTION".  We assume that the user
 
2476
                         * will interpret the error as meaning the BEGIN failed to get him
 
2477
                         * into a transaction block, so we should abort and return to idle
 
2478
                         * state.
 
2479
                         */
 
2480
                case TBLOCK_BEGIN:
 
2481
                        AbortTransaction();
 
2482
                        CleanupTransaction();
 
2483
                        s->blockState = TBLOCK_DEFAULT;
 
2484
                        break;
 
2485
 
 
2486
                        /*
 
2487
                         * We are somewhere in a transaction block and we've gotten a
 
2488
                         * failure, so we abort the transaction and set up the persistent
 
2489
                         * ABORT state.  We will stay in ABORT until we get a ROLLBACK.
 
2490
                         */
 
2491
                case TBLOCK_INPROGRESS:
 
2492
                        AbortTransaction();
 
2493
                        s->blockState = TBLOCK_ABORT;
 
2494
                        /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
 
2495
                        break;
 
2496
 
 
2497
                        /*
 
2498
                         * Here, we failed while trying to COMMIT.      Clean up the
 
2499
                         * transaction and return to idle state (we do not want to stay in
 
2500
                         * the transaction).
 
2501
                         */
 
2502
                case TBLOCK_END:
 
2503
                        AbortTransaction();
 
2504
                        CleanupTransaction();
 
2505
                        s->blockState = TBLOCK_DEFAULT;
 
2506
                        break;
 
2507
 
 
2508
                        /*
 
2509
                         * Here, we are already in an aborted transaction state and are
 
2510
                         * waiting for a ROLLBACK, but for some reason we failed again! So
 
2511
                         * we just remain in the abort state.
 
2512
                         */
 
2513
                case TBLOCK_ABORT:
 
2514
                case TBLOCK_SUBABORT:
 
2515
                        break;
 
2516
 
 
2517
                        /*
 
2518
                         * We are in a failed transaction and we got the ROLLBACK command.
 
2519
                         * We have already aborted, we just need to cleanup and go to idle
 
2520
                         * state.
 
2521
                         */
 
2522
                case TBLOCK_ABORT_END:
 
2523
                        CleanupTransaction();
 
2524
                        s->blockState = TBLOCK_DEFAULT;
 
2525
                        break;
 
2526
 
 
2527
                        /*
 
2528
                         * We are in a live transaction and we got a ROLLBACK command.
 
2529
                         * Abort, cleanup, go to idle state.
 
2530
                         */
 
2531
                case TBLOCK_ABORT_PENDING:
 
2532
                        AbortTransaction();
 
2533
                        CleanupTransaction();
 
2534
                        s->blockState = TBLOCK_DEFAULT;
 
2535
                        break;
 
2536
 
 
2537
                        /*
 
2538
                         * Here, we failed while trying to PREPARE.  Clean up the
 
2539
                         * transaction and return to idle state (we do not want to stay in
 
2540
                         * the transaction).
 
2541
                         */
 
2542
                case TBLOCK_PREPARE:
 
2543
                        AbortTransaction();
 
2544
                        CleanupTransaction();
 
2545
                        s->blockState = TBLOCK_DEFAULT;
 
2546
                        break;
 
2547
 
 
2548
                        /*
 
2549
                         * We got an error inside a subtransaction.  Abort just the
 
2550
                         * subtransaction, and go to the persistent SUBABORT state until
 
2551
                         * we get ROLLBACK.
 
2552
                         */
 
2553
                case TBLOCK_SUBINPROGRESS:
 
2554
                        AbortSubTransaction();
 
2555
                        s->blockState = TBLOCK_SUBABORT;
 
2556
                        break;
 
2557
 
 
2558
                        /*
 
2559
                         * If we failed while trying to create a subtransaction, clean up
 
2560
                         * the broken subtransaction and abort the parent.      The same
 
2561
                         * applies if we get a failure while ending a subtransaction.
 
2562
                         */
 
2563
                case TBLOCK_SUBBEGIN:
 
2564
                case TBLOCK_SUBEND:
 
2565
                case TBLOCK_SUBABORT_PENDING:
 
2566
                case TBLOCK_SUBRESTART:
 
2567
                        AbortSubTransaction();
 
2568
                        CleanupSubTransaction();
 
2569
                        AbortCurrentTransaction();
 
2570
                        break;
 
2571
 
 
2572
                        /*
 
2573
                         * Same as above, except the Abort() was already done.
 
2574
                         */
 
2575
                case TBLOCK_SUBABORT_END:
 
2576
                case TBLOCK_SUBABORT_RESTART:
 
2577
                        CleanupSubTransaction();
 
2578
                        AbortCurrentTransaction();
 
2579
                        break;
 
2580
        }
 
2581
}
 
2582
 
 
2583
/*
 
2584
 *      PreventTransactionChain
 
2585
 *
 
2586
 *      This routine is to be called by statements that must not run inside
 
2587
 *      a transaction block, typically because they have non-rollback-able
 
2588
 *      side effects or do internal commits.
 
2589
 *
 
2590
 *      If we have already started a transaction block, issue an error; also issue
 
2591
 *      an error if we appear to be running inside a user-defined function (which
 
2592
 *      could issue more commands and possibly cause a failure after the statement
 
2593
 *      completes).  Subtransactions are verboten too.
 
2594
 *
 
2595
 *      isTopLevel: passed down from ProcessUtility to determine whether we are
 
2596
 *      inside a function or multi-query querystring.  (We will always fail if
 
2597
 *      this is false, but it's convenient to centralize the check here instead of
 
2598
 *      making callers do it.)
 
2599
 *      stmtType: statement type name, for error messages.
 
2600
 */
 
2601
void
 
2602
PreventTransactionChain(bool isTopLevel, const char *stmtType)
 
2603
{
 
2604
        /*
 
2605
         * xact block already started?
 
2606
         */
 
2607
        if (IsTransactionBlock())
 
2608
                ereport(ERROR,
 
2609
                                (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
 
2610
                /* translator: %s represents an SQL statement name */
 
2611
                                 errmsg("%s cannot run inside a transaction block",
 
2612
                                                stmtType)));
 
2613
 
 
2614
        /*
 
2615
         * subtransaction?
 
2616
         */
 
2617
        if (IsSubTransaction())
 
2618
                ereport(ERROR,
 
2619
                                (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
 
2620
                /* translator: %s represents an SQL statement name */
 
2621
                                 errmsg("%s cannot run inside a subtransaction",
 
2622
                                                stmtType)));
 
2623
 
 
2624
        /*
 
2625
         * inside a function call?
 
2626
         */
 
2627
        if (!isTopLevel)
 
2628
                ereport(ERROR,
 
2629
                                (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
 
2630
                /* translator: %s represents an SQL statement name */
 
2631
                                 errmsg("%s cannot be executed from a function or multi-command string",
 
2632
                                                stmtType)));
 
2633
 
 
2634
        /* If we got past IsTransactionBlock test, should be in default state */
 
2635
        if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
 
2636
                CurrentTransactionState->blockState != TBLOCK_STARTED)
 
2637
                elog(FATAL, "cannot prevent transaction chain");
 
2638
        /* all okay */
 
2639
}
 
2640
 
 
2641
/*
 
2642
 *      RequireTransactionChain
 
2643
 *
 
2644
 *      This routine is to be called by statements that must run inside
 
2645
 *      a transaction block, because they have no effects that persist past
 
2646
 *      transaction end (and so calling them outside a transaction block
 
2647
 *      is presumably an error).  DECLARE CURSOR is an example.
 
2648
 *
 
2649
 *      If we appear to be running inside a user-defined function, we do not
 
2650
 *      issue an error, since the function could issue more commands that make
 
2651
 *      use of the current statement's results.  Likewise subtransactions.
 
2652
 *      Thus this is an inverse for PreventTransactionChain.
 
2653
 *
 
2654
 *      isTopLevel: passed down from ProcessUtility to determine whether we are
 
2655
 *      inside a function.
 
2656
 *      stmtType: statement type name, for error messages.
 
2657
 */
 
2658
void
 
2659
RequireTransactionChain(bool isTopLevel, const char *stmtType)
 
2660
{
 
2661
        /*
 
2662
         * xact block already started?
 
2663
         */
 
2664
        if (IsTransactionBlock())
 
2665
                return;
 
2666
 
 
2667
        /*
 
2668
         * subtransaction?
 
2669
         */
 
2670
        if (IsSubTransaction())
 
2671
                return;
 
2672
 
 
2673
        /*
 
2674
         * inside a function call?
 
2675
         */
 
2676
        if (!isTopLevel)
 
2677
                return;
 
2678
 
 
2679
        ereport(ERROR,
 
2680
                        (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
 
2681
        /* translator: %s represents an SQL statement name */
 
2682
                         errmsg("%s can only be used in transaction blocks",
 
2683
                                        stmtType)));
 
2684
}
 
2685
 
 
2686
/*
 
2687
 *      IsInTransactionChain
 
2688
 *
 
2689
 *      This routine is for statements that need to behave differently inside
 
2690
 *      a transaction block than when running as single commands.  ANALYZE is
 
2691
 *      currently the only example.
 
2692
 *
 
2693
 *      isTopLevel: passed down from ProcessUtility to determine whether we are
 
2694
 *      inside a function.
 
2695
 */
 
2696
bool
 
2697
IsInTransactionChain(bool isTopLevel)
 
2698
{
 
2699
        /*
 
2700
         * Return true on same conditions that would make PreventTransactionChain
 
2701
         * error out
 
2702
         */
 
2703
        if (IsTransactionBlock())
 
2704
                return true;
 
2705
 
 
2706
        if (IsSubTransaction())
 
2707
                return true;
 
2708
 
 
2709
        if (!isTopLevel)
 
2710
                return true;
 
2711
 
 
2712
        if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
 
2713
                CurrentTransactionState->blockState != TBLOCK_STARTED)
 
2714
                return true;
 
2715
 
 
2716
        return false;
 
2717
}
 
2718
 
 
2719
 
 
2720
/*
 
2721
 * Register or deregister callback functions for start- and end-of-xact
 
2722
 * operations.
 
2723
 *
 
2724
 * These functions are intended for use by dynamically loaded modules.
 
2725
 * For built-in modules we generally just hardwire the appropriate calls
 
2726
 * (mainly because it's easier to control the order that way, where needed).
 
2727
 *
 
2728
 * At transaction end, the callback occurs post-commit or post-abort, so the
 
2729
 * callback functions can only do noncritical cleanup.
 
2730
 */
 
2731
void
 
2732
RegisterXactCallback(XactCallback callback, void *arg)
 
2733
{
 
2734
        XactCallbackItem *item;
 
2735
 
 
2736
        item = (XactCallbackItem *)
 
2737
                MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
 
2738
        item->callback = callback;
 
2739
        item->arg = arg;
 
2740
        item->next = Xact_callbacks;
 
2741
        Xact_callbacks = item;
 
2742
}
 
2743
 
 
2744
void
 
2745
UnregisterXactCallback(XactCallback callback, void *arg)
 
2746
{
 
2747
        XactCallbackItem *item;
 
2748
        XactCallbackItem *prev;
 
2749
 
 
2750
        prev = NULL;
 
2751
        for (item = Xact_callbacks; item; prev = item, item = item->next)
 
2752
        {
 
2753
                if (item->callback == callback && item->arg == arg)
 
2754
                {
 
2755
                        if (prev)
 
2756
                                prev->next = item->next;
 
2757
                        else
 
2758
                                Xact_callbacks = item->next;
 
2759
                        pfree(item);
 
2760
                        break;
 
2761
                }
 
2762
        }
 
2763
}
 
2764
 
 
2765
static void
 
2766
CallXactCallbacks(XactEvent event)
 
2767
{
 
2768
        XactCallbackItem *item;
 
2769
 
 
2770
        for (item = Xact_callbacks; item; item = item->next)
 
2771
                (*item->callback) (event, item->arg);
 
2772
}
 
2773
 
 
2774
 
 
2775
/*
 
2776
 * Register or deregister callback functions for start- and end-of-subxact
 
2777
 * operations.
 
2778
 *
 
2779
 * Pretty much same as above, but for subtransaction events.
 
2780
 *
 
2781
 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
 
2782
 * so the callback functions can only do noncritical cleanup.  At
 
2783
 * subtransaction start, the callback is called when the subtransaction has
 
2784
 * finished initializing.
 
2785
 */
 
2786
void
 
2787
RegisterSubXactCallback(SubXactCallback callback, void *arg)
 
2788
{
 
2789
        SubXactCallbackItem *item;
 
2790
 
 
2791
        item = (SubXactCallbackItem *)
 
2792
                MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
 
2793
        item->callback = callback;
 
2794
        item->arg = arg;
 
2795
        item->next = SubXact_callbacks;
 
2796
        SubXact_callbacks = item;
 
2797
}
 
2798
 
 
2799
void
 
2800
UnregisterSubXactCallback(SubXactCallback callback, void *arg)
 
2801
{
 
2802
        SubXactCallbackItem *item;
 
2803
        SubXactCallbackItem *prev;
 
2804
 
 
2805
        prev = NULL;
 
2806
        for (item = SubXact_callbacks; item; prev = item, item = item->next)
 
2807
        {
 
2808
                if (item->callback == callback && item->arg == arg)
 
2809
                {
 
2810
                        if (prev)
 
2811
                                prev->next = item->next;
 
2812
                        else
 
2813
                                SubXact_callbacks = item->next;
 
2814
                        pfree(item);
 
2815
                        break;
 
2816
                }
 
2817
        }
 
2818
}
 
2819
 
 
2820
static void
 
2821
CallSubXactCallbacks(SubXactEvent event,
 
2822
                                         SubTransactionId mySubid,
 
2823
                                         SubTransactionId parentSubid)
 
2824
{
 
2825
        SubXactCallbackItem *item;
 
2826
 
 
2827
        for (item = SubXact_callbacks; item; item = item->next)
 
2828
                (*item->callback) (event, mySubid, parentSubid, item->arg);
 
2829
}
 
2830
 
 
2831
 
 
2832
/* ----------------------------------------------------------------
 
2833
 *                                         transaction block support
 
2834
 * ----------------------------------------------------------------
 
2835
 */
 
2836
 
 
2837
/*
 
2838
 *      BeginTransactionBlock
 
2839
 *              This executes a BEGIN command.
 
2840
 */
 
2841
void
 
2842
BeginTransactionBlock(void)
 
2843
{
 
2844
        TransactionState s = CurrentTransactionState;
 
2845
 
 
2846
        switch (s->blockState)
 
2847
        {
 
2848
                        /*
 
2849
                         * We are not inside a transaction block, so allow one to begin.
 
2850
                         */
 
2851
                case TBLOCK_STARTED:
 
2852
                        s->blockState = TBLOCK_BEGIN;
 
2853
                        break;
 
2854
 
 
2855
                        /*
 
2856
                         * Already a transaction block in progress.
 
2857
                         */
 
2858
                case TBLOCK_INPROGRESS:
 
2859
                case TBLOCK_SUBINPROGRESS:
 
2860
                case TBLOCK_ABORT:
 
2861
                case TBLOCK_SUBABORT:
 
2862
                        ereport(WARNING,
 
2863
                                        (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
 
2864
                                         errmsg("there is already a transaction in progress")));
 
2865
                        break;
 
2866
 
 
2867
                        /* These cases are invalid. */
 
2868
                case TBLOCK_DEFAULT:
 
2869
                case TBLOCK_BEGIN:
 
2870
                case TBLOCK_SUBBEGIN:
 
2871
                case TBLOCK_END:
 
2872
                case TBLOCK_SUBEND:
 
2873
                case TBLOCK_ABORT_END:
 
2874
                case TBLOCK_SUBABORT_END:
 
2875
                case TBLOCK_ABORT_PENDING:
 
2876
                case TBLOCK_SUBABORT_PENDING:
 
2877
                case TBLOCK_SUBRESTART:
 
2878
                case TBLOCK_SUBABORT_RESTART:
 
2879
                case TBLOCK_PREPARE:
 
2880
                        elog(FATAL, "BeginTransactionBlock: unexpected state %s",
 
2881
                                 BlockStateAsString(s->blockState));
 
2882
                        break;
 
2883
        }
 
2884
}
 
2885
 
 
2886
/*
 
2887
 *      PrepareTransactionBlock
 
2888
 *              This executes a PREPARE command.
 
2889
 *
 
2890
 * Since PREPARE may actually do a ROLLBACK, the result indicates what
 
2891
 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
 
2892
 *
 
2893
 * Note that we don't actually do anything here except change blockState.
 
2894
 * The real work will be done in the upcoming PrepareTransaction().
 
2895
 * We do it this way because it's not convenient to change memory context,
 
2896
 * resource owner, etc while executing inside a Portal.
 
2897
 */
 
2898
bool
 
2899
PrepareTransactionBlock(char *gid)
 
2900
{
 
2901
        TransactionState s;
 
2902
        bool            result;
 
2903
 
 
2904
        /* Set up to commit the current transaction */
 
2905
        result = EndTransactionBlock();
 
2906
 
 
2907
        /* If successful, change outer tblock state to PREPARE */
 
2908
        if (result)
 
2909
        {
 
2910
                s = CurrentTransactionState;
 
2911
 
 
2912
                while (s->parent != NULL)
 
2913
                        s = s->parent;
 
2914
 
 
2915
                if (s->blockState == TBLOCK_END)
 
2916
                {
 
2917
                        /* Save GID where PrepareTransaction can find it again */
 
2918
                        prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
 
2919
 
 
2920
                        s->blockState = TBLOCK_PREPARE;
 
2921
                }
 
2922
                else
 
2923
                {
 
2924
                        /*
 
2925
                         * ignore case where we are not in a transaction;
 
2926
                         * EndTransactionBlock already issued a warning.
 
2927
                         */
 
2928
                        Assert(s->blockState == TBLOCK_STARTED);
 
2929
                        /* Don't send back a PREPARE result tag... */
 
2930
                        result = false;
 
2931
                }
 
2932
        }
 
2933
 
 
2934
        return result;
 
2935
}
 
2936
 
 
2937
/*
 
2938
 *      EndTransactionBlock
 
2939
 *              This executes a COMMIT command.
 
2940
 *
 
2941
 * Since COMMIT may actually do a ROLLBACK, the result indicates what
 
2942
 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
 
2943
 *
 
2944
 * Note that we don't actually do anything here except change blockState.
 
2945
 * The real work will be done in the upcoming CommitTransactionCommand().
 
2946
 * We do it this way because it's not convenient to change memory context,
 
2947
 * resource owner, etc while executing inside a Portal.
 
2948
 */
 
2949
bool
 
2950
EndTransactionBlock(void)
 
2951
{
 
2952
        TransactionState s = CurrentTransactionState;
 
2953
        bool            result = false;
 
2954
 
 
2955
        switch (s->blockState)
 
2956
        {
 
2957
                        /*
 
2958
                         * We are in a transaction block, so tell CommitTransactionCommand
 
2959
                         * to COMMIT.
 
2960
                         */
 
2961
                case TBLOCK_INPROGRESS:
 
2962
                        s->blockState = TBLOCK_END;
 
2963
                        result = true;
 
2964
                        break;
 
2965
 
 
2966
                        /*
 
2967
                         * We are in a failed transaction block.  Tell
 
2968
                         * CommitTransactionCommand it's time to exit the block.
 
2969
                         */
 
2970
                case TBLOCK_ABORT:
 
2971
                        s->blockState = TBLOCK_ABORT_END;
 
2972
                        break;
 
2973
 
 
2974
                        /*
 
2975
                         * We are in a live subtransaction block.  Set up to subcommit all
 
2976
                         * open subtransactions and then commit the main transaction.
 
2977
                         */
 
2978
                case TBLOCK_SUBINPROGRESS:
 
2979
                        while (s->parent != NULL)
 
2980
                        {
 
2981
                                if (s->blockState == TBLOCK_SUBINPROGRESS)
 
2982
                                        s->blockState = TBLOCK_SUBEND;
 
2983
                                else
 
2984
                                        elog(FATAL, "EndTransactionBlock: unexpected state %s",
 
2985
                                                 BlockStateAsString(s->blockState));
 
2986
                                s = s->parent;
 
2987
                        }
 
2988
                        if (s->blockState == TBLOCK_INPROGRESS)
 
2989
                                s->blockState = TBLOCK_END;
 
2990
                        else
 
2991
                                elog(FATAL, "EndTransactionBlock: unexpected state %s",
 
2992
                                         BlockStateAsString(s->blockState));
 
2993
                        result = true;
 
2994
                        break;
 
2995
 
 
2996
                        /*
 
2997
                         * Here we are inside an aborted subtransaction.  Treat the COMMIT
 
2998
                         * as ROLLBACK: set up to abort everything and exit the main
 
2999
                         * transaction.
 
3000
                         */
 
3001
                case TBLOCK_SUBABORT:
 
3002
                        while (s->parent != NULL)
 
3003
                        {
 
3004
                                if (s->blockState == TBLOCK_SUBINPROGRESS)
 
3005
                                        s->blockState = TBLOCK_SUBABORT_PENDING;
 
3006
                                else if (s->blockState == TBLOCK_SUBABORT)
 
3007
                                        s->blockState = TBLOCK_SUBABORT_END;
 
3008
                                else
 
3009
                                        elog(FATAL, "EndTransactionBlock: unexpected state %s",
 
3010
                                                 BlockStateAsString(s->blockState));
 
3011
                                s = s->parent;
 
3012
                        }
 
3013
                        if (s->blockState == TBLOCK_INPROGRESS)
 
3014
                                s->blockState = TBLOCK_ABORT_PENDING;
 
3015
                        else if (s->blockState == TBLOCK_ABORT)
 
3016
                                s->blockState = TBLOCK_ABORT_END;
 
3017
                        else
 
3018
                                elog(FATAL, "EndTransactionBlock: unexpected state %s",
 
3019
                                         BlockStateAsString(s->blockState));
 
3020
                        break;
 
3021
 
 
3022
                        /*
 
3023
                         * The user issued COMMIT when not inside a transaction.  Issue a
 
3024
                         * WARNING, staying in TBLOCK_STARTED state.  The upcoming call to
 
3025
                         * CommitTransactionCommand() will then close the transaction and
 
3026
                         * put us back into the default state.
 
3027
                         */
 
3028
                case TBLOCK_STARTED:
 
3029
                        ereport(WARNING,
 
3030
                                        (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
 
3031
                                         errmsg("there is no transaction in progress")));
 
3032
                        result = true;
 
3033
                        break;
 
3034
 
 
3035
                        /* These cases are invalid. */
 
3036
                case TBLOCK_DEFAULT:
 
3037
                case TBLOCK_BEGIN:
 
3038
                case TBLOCK_SUBBEGIN:
 
3039
                case TBLOCK_END:
 
3040
                case TBLOCK_SUBEND:
 
3041
                case TBLOCK_ABORT_END:
 
3042
                case TBLOCK_SUBABORT_END:
 
3043
                case TBLOCK_ABORT_PENDING:
 
3044
                case TBLOCK_SUBABORT_PENDING:
 
3045
                case TBLOCK_SUBRESTART:
 
3046
                case TBLOCK_SUBABORT_RESTART:
 
3047
                case TBLOCK_PREPARE:
 
3048
                        elog(FATAL, "EndTransactionBlock: unexpected state %s",
 
3049
                                 BlockStateAsString(s->blockState));
 
3050
                        break;
 
3051
        }
 
3052
 
 
3053
        return result;
 
3054
}
 
3055
 
 
3056
/*
 
3057
 *      UserAbortTransactionBlock
 
3058
 *              This executes a ROLLBACK command.
 
3059
 *
 
3060
 * As above, we don't actually do anything here except change blockState.
 
3061
 */
 
3062
void
 
3063
UserAbortTransactionBlock(void)
 
3064
{
 
3065
        TransactionState s = CurrentTransactionState;
 
3066
 
 
3067
        switch (s->blockState)
 
3068
        {
 
3069
                        /*
 
3070
                         * We are inside a transaction block and we got a ROLLBACK command
 
3071
                         * from the user, so tell CommitTransactionCommand to abort and
 
3072
                         * exit the transaction block.
 
3073
                         */
 
3074
                case TBLOCK_INPROGRESS:
 
3075
                        s->blockState = TBLOCK_ABORT_PENDING;
 
3076
                        break;
 
3077
 
 
3078
                        /*
 
3079
                         * We are inside a failed transaction block and we got a ROLLBACK
 
3080
                         * command from the user.  Abort processing is already done, so
 
3081
                         * CommitTransactionCommand just has to cleanup and go back to
 
3082
                         * idle state.
 
3083
                         */
 
3084
                case TBLOCK_ABORT:
 
3085
                        s->blockState = TBLOCK_ABORT_END;
 
3086
                        break;
 
3087
 
 
3088
                        /*
 
3089
                         * We are inside a subtransaction.      Mark everything up to top
 
3090
                         * level as exitable.
 
3091
                         */
 
3092
                case TBLOCK_SUBINPROGRESS:
 
3093
                case TBLOCK_SUBABORT:
 
3094
                        while (s->parent != NULL)
 
3095
                        {
 
3096
                                if (s->blockState == TBLOCK_SUBINPROGRESS)
 
3097
                                        s->blockState = TBLOCK_SUBABORT_PENDING;
 
3098
                                else if (s->blockState == TBLOCK_SUBABORT)
 
3099
                                        s->blockState = TBLOCK_SUBABORT_END;
 
3100
                                else
 
3101
                                        elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
 
3102
                                                 BlockStateAsString(s->blockState));
 
3103
                                s = s->parent;
 
3104
                        }
 
3105
                        if (s->blockState == TBLOCK_INPROGRESS)
 
3106
                                s->blockState = TBLOCK_ABORT_PENDING;
 
3107
                        else if (s->blockState == TBLOCK_ABORT)
 
3108
                                s->blockState = TBLOCK_ABORT_END;
 
3109
                        else
 
3110
                                elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
 
3111
                                         BlockStateAsString(s->blockState));
 
3112
                        break;
 
3113
 
 
3114
                        /*
 
3115
                         * The user issued ABORT when not inside a transaction. Issue a
 
3116
                         * WARNING and go to abort state.  The upcoming call to
 
3117
                         * CommitTransactionCommand() will then put us back into the
 
3118
                         * default state.
 
3119
                         */
 
3120
                case TBLOCK_STARTED:
 
3121
                        ereport(NOTICE,
 
3122
                                        (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
 
3123
                                         errmsg("there is no transaction in progress")));
 
3124
                        s->blockState = TBLOCK_ABORT_PENDING;
 
3125
                        break;
 
3126
 
 
3127
                        /* These cases are invalid. */
 
3128
                case TBLOCK_DEFAULT:
 
3129
                case TBLOCK_BEGIN:
 
3130
                case TBLOCK_SUBBEGIN:
 
3131
                case TBLOCK_END:
 
3132
                case TBLOCK_SUBEND:
 
3133
                case TBLOCK_ABORT_END:
 
3134
                case TBLOCK_SUBABORT_END:
 
3135
                case TBLOCK_ABORT_PENDING:
 
3136
                case TBLOCK_SUBABORT_PENDING:
 
3137
                case TBLOCK_SUBRESTART:
 
3138
                case TBLOCK_SUBABORT_RESTART:
 
3139
                case TBLOCK_PREPARE:
 
3140
                        elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
 
3141
                                 BlockStateAsString(s->blockState));
 
3142
                        break;
 
3143
        }
 
3144
}
 
3145
 
 
3146
/*
 
3147
 * DefineSavepoint
 
3148
 *              This executes a SAVEPOINT command.
 
3149
 */
 
3150
void
 
3151
DefineSavepoint(char *name)
 
3152
{
 
3153
        TransactionState s = CurrentTransactionState;
 
3154
 
 
3155
        switch (s->blockState)
 
3156
        {
 
3157
                case TBLOCK_INPROGRESS:
 
3158
                case TBLOCK_SUBINPROGRESS:
 
3159
                        /* Normal subtransaction start */
 
3160
                        PushTransaction();
 
3161
                        s = CurrentTransactionState;            /* changed by push */
 
3162
 
 
3163
                        /*
 
3164
                         * Savepoint names, like the TransactionState block itself, live
 
3165
                         * in TopTransactionContext.
 
3166
                         */
 
3167
                        if (name)
 
3168
                                s->name = MemoryContextStrdup(TopTransactionContext, name);
 
3169
                        break;
 
3170
 
 
3171
                        /* These cases are invalid. */
 
3172
                case TBLOCK_DEFAULT:
 
3173
                case TBLOCK_STARTED:
 
3174
                case TBLOCK_BEGIN:
 
3175
                case TBLOCK_SUBBEGIN:
 
3176
                case TBLOCK_END:
 
3177
                case TBLOCK_SUBEND:
 
3178
                case TBLOCK_ABORT:
 
3179
                case TBLOCK_SUBABORT:
 
3180
                case TBLOCK_ABORT_END:
 
3181
                case TBLOCK_SUBABORT_END:
 
3182
                case TBLOCK_ABORT_PENDING:
 
3183
                case TBLOCK_SUBABORT_PENDING:
 
3184
                case TBLOCK_SUBRESTART:
 
3185
                case TBLOCK_SUBABORT_RESTART:
 
3186
                case TBLOCK_PREPARE:
 
3187
                        elog(FATAL, "DefineSavepoint: unexpected state %s",
 
3188
                                 BlockStateAsString(s->blockState));
 
3189
                        break;
 
3190
        }
 
3191
}
 
3192
 
 
3193
/*
 
3194
 * ReleaseSavepoint
 
3195
 *              This executes a RELEASE command.
 
3196
 *
 
3197
 * As above, we don't actually do anything here except change blockState.
 
3198
 */
 
3199
void
 
3200
ReleaseSavepoint(List *options)
 
3201
{
 
3202
        TransactionState s = CurrentTransactionState;
 
3203
        TransactionState target,
 
3204
                                xact;
 
3205
        ListCell   *cell;
 
3206
        char       *name = NULL;
 
3207
 
 
3208
        switch (s->blockState)
 
3209
        {
 
3210
                        /*
 
3211
                         * We can't rollback to a savepoint if there is no savepoint
 
3212
                         * defined.
 
3213
                         */
 
3214
                case TBLOCK_INPROGRESS:
 
3215
                        ereport(ERROR,
 
3216
                                        (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
 
3217
                                         errmsg("no such savepoint")));
 
3218
                        break;
 
3219
 
 
3220
                        /*
 
3221
                         * We are in a non-aborted subtransaction.      This is the only valid
 
3222
                         * case.
 
3223
                         */
 
3224
                case TBLOCK_SUBINPROGRESS:
 
3225
                        break;
 
3226
 
 
3227
                        /* These cases are invalid. */
 
3228
                case TBLOCK_DEFAULT:
 
3229
                case TBLOCK_STARTED:
 
3230
                case TBLOCK_BEGIN:
 
3231
                case TBLOCK_SUBBEGIN:
 
3232
                case TBLOCK_END:
 
3233
                case TBLOCK_SUBEND:
 
3234
                case TBLOCK_ABORT:
 
3235
                case TBLOCK_SUBABORT:
 
3236
                case TBLOCK_ABORT_END:
 
3237
                case TBLOCK_SUBABORT_END:
 
3238
                case TBLOCK_ABORT_PENDING:
 
3239
                case TBLOCK_SUBABORT_PENDING:
 
3240
                case TBLOCK_SUBRESTART:
 
3241
                case TBLOCK_SUBABORT_RESTART:
 
3242
                case TBLOCK_PREPARE:
 
3243
                        elog(FATAL, "ReleaseSavepoint: unexpected state %s",
 
3244
                                 BlockStateAsString(s->blockState));
 
3245
                        break;
 
3246
        }
 
3247
 
 
3248
        foreach(cell, options)
 
3249
        {
 
3250
                DefElem    *elem = lfirst(cell);
 
3251
 
 
3252
                if (strcmp(elem->defname, "savepoint_name") == 0)
 
3253
                        name = strVal(elem->arg);
 
3254
        }
 
3255
 
 
3256
        Assert(PointerIsValid(name));
 
3257
 
 
3258
        for (target = s; PointerIsValid(target); target = target->parent)
 
3259
        {
 
3260
                if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
 
3261
                        break;
 
3262
        }
 
3263
 
 
3264
        if (!PointerIsValid(target))
 
3265
                ereport(ERROR,
 
3266
                                (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
 
3267
                                 errmsg("no such savepoint")));
 
3268
 
 
3269
        /* disallow crossing savepoint level boundaries */
 
3270
        if (target->savepointLevel != s->savepointLevel)
 
3271
                ereport(ERROR,
 
3272
                                (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
 
3273
                                 errmsg("no such savepoint")));
 
3274
 
 
3275
        /*
 
3276
         * Mark "commit pending" all subtransactions up to the target
 
3277
         * subtransaction.      The actual commits will happen when control gets to
 
3278
         * CommitTransactionCommand.
 
3279
         */
 
3280
        xact = CurrentTransactionState;
 
3281
        for (;;)
 
3282
        {
 
3283
                Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
 
3284
                xact->blockState = TBLOCK_SUBEND;
 
3285
                if (xact == target)
 
3286
                        break;
 
3287
                xact = xact->parent;
 
3288
                Assert(PointerIsValid(xact));
 
3289
        }
 
3290
}
 
3291
 
 
3292
/*
 
3293
 * RollbackToSavepoint
 
3294
 *              This executes a ROLLBACK TO <savepoint> command.
 
3295
 *
 
3296
 * As above, we don't actually do anything here except change blockState.
 
3297
 */
 
3298
void
 
3299
RollbackToSavepoint(List *options)
 
3300
{
 
3301
        TransactionState s = CurrentTransactionState;
 
3302
        TransactionState target,
 
3303
                                xact;
 
3304
        ListCell   *cell;
 
3305
        char       *name = NULL;
 
3306
 
 
3307
        switch (s->blockState)
 
3308
        {
 
3309
                        /*
 
3310
                         * We can't rollback to a savepoint if there is no savepoint
 
3311
                         * defined.
 
3312
                         */
 
3313
                case TBLOCK_INPROGRESS:
 
3314
                case TBLOCK_ABORT:
 
3315
                        ereport(ERROR,
 
3316
                                        (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
 
3317
                                         errmsg("no such savepoint")));
 
3318
                        break;
 
3319
 
 
3320
                        /*
 
3321
                         * There is at least one savepoint, so proceed.
 
3322
                         */
 
3323
                case TBLOCK_SUBINPROGRESS:
 
3324
                case TBLOCK_SUBABORT:
 
3325
                        break;
 
3326
 
 
3327
                        /* These cases are invalid. */
 
3328
                case TBLOCK_DEFAULT:
 
3329
                case TBLOCK_STARTED:
 
3330
                case TBLOCK_BEGIN:
 
3331
                case TBLOCK_SUBBEGIN:
 
3332
                case TBLOCK_END:
 
3333
                case TBLOCK_SUBEND:
 
3334
                case TBLOCK_ABORT_END:
 
3335
                case TBLOCK_SUBABORT_END:
 
3336
                case TBLOCK_ABORT_PENDING:
 
3337
                case TBLOCK_SUBABORT_PENDING:
 
3338
                case TBLOCK_SUBRESTART:
 
3339
                case TBLOCK_SUBABORT_RESTART:
 
3340
                case TBLOCK_PREPARE:
 
3341
                        elog(FATAL, "RollbackToSavepoint: unexpected state %s",
 
3342
                                 BlockStateAsString(s->blockState));
 
3343
                        break;
 
3344
        }
 
3345
 
 
3346
        foreach(cell, options)
 
3347
        {
 
3348
                DefElem    *elem = lfirst(cell);
 
3349
 
 
3350
                if (strcmp(elem->defname, "savepoint_name") == 0)
 
3351
                        name = strVal(elem->arg);
 
3352
        }
 
3353
 
 
3354
        Assert(PointerIsValid(name));
 
3355
 
 
3356
        for (target = s; PointerIsValid(target); target = target->parent)
 
3357
        {
 
3358
                if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
 
3359
                        break;
 
3360
        }
 
3361
 
 
3362
        if (!PointerIsValid(target))
 
3363
                ereport(ERROR,
 
3364
                                (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
 
3365
                                 errmsg("no such savepoint")));
 
3366
 
 
3367
        /* disallow crossing savepoint level boundaries */
 
3368
        if (target->savepointLevel != s->savepointLevel)
 
3369
                ereport(ERROR,
 
3370
                                (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
 
3371
                                 errmsg("no such savepoint")));
 
3372
 
 
3373
        /*
 
3374
         * Mark "abort pending" all subtransactions up to the target
 
3375
         * subtransaction.      The actual aborts will happen when control gets to
 
3376
         * CommitTransactionCommand.
 
3377
         */
 
3378
        xact = CurrentTransactionState;
 
3379
        for (;;)
 
3380
        {
 
3381
                if (xact == target)
 
3382
                        break;
 
3383
                if (xact->blockState == TBLOCK_SUBINPROGRESS)
 
3384
                        xact->blockState = TBLOCK_SUBABORT_PENDING;
 
3385
                else if (xact->blockState == TBLOCK_SUBABORT)
 
3386
                        xact->blockState = TBLOCK_SUBABORT_END;
 
3387
                else
 
3388
                        elog(FATAL, "RollbackToSavepoint: unexpected state %s",
 
3389
                                 BlockStateAsString(xact->blockState));
 
3390
                xact = xact->parent;
 
3391
                Assert(PointerIsValid(xact));
 
3392
        }
 
3393
 
 
3394
        /* And mark the target as "restart pending" */
 
3395
        if (xact->blockState == TBLOCK_SUBINPROGRESS)
 
3396
                xact->blockState = TBLOCK_SUBRESTART;
 
3397
        else if (xact->blockState == TBLOCK_SUBABORT)
 
3398
                xact->blockState = TBLOCK_SUBABORT_RESTART;
 
3399
        else
 
3400
                elog(FATAL, "RollbackToSavepoint: unexpected state %s",
 
3401
                         BlockStateAsString(xact->blockState));
 
3402
}
 
3403
 
 
3404
/*
 
3405
 * BeginInternalSubTransaction
 
3406
 *              This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
 
3407
 *              TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
 
3408
 *              used in functions that might be called when not inside a BEGIN block
 
3409
 *              or when running deferred triggers at COMMIT/PREPARE time.  Also, it
 
3410
 *              automatically does CommitTransactionCommand/StartTransactionCommand
 
3411
 *              instead of expecting the caller to do it.
 
3412
 */
 
3413
void
 
3414
BeginInternalSubTransaction(char *name)
 
3415
{
 
3416
        TransactionState s = CurrentTransactionState;
 
3417
 
 
3418
        switch (s->blockState)
 
3419
        {
 
3420
                case TBLOCK_STARTED:
 
3421
                case TBLOCK_INPROGRESS:
 
3422
                case TBLOCK_END:
 
3423
                case TBLOCK_PREPARE:
 
3424
                case TBLOCK_SUBINPROGRESS:
 
3425
                        /* Normal subtransaction start */
 
3426
                        PushTransaction();
 
3427
                        s = CurrentTransactionState;            /* changed by push */
 
3428
 
 
3429
                        /*
 
3430
                         * Savepoint names, like the TransactionState block itself, live
 
3431
                         * in TopTransactionContext.
 
3432
                         */
 
3433
                        if (name)
 
3434
                                s->name = MemoryContextStrdup(TopTransactionContext, name);
 
3435
                        break;
 
3436
 
 
3437
                        /* These cases are invalid. */
 
3438
                case TBLOCK_DEFAULT:
 
3439
                case TBLOCK_BEGIN:
 
3440
                case TBLOCK_SUBBEGIN:
 
3441
                case TBLOCK_SUBEND:
 
3442
                case TBLOCK_ABORT:
 
3443
                case TBLOCK_SUBABORT:
 
3444
                case TBLOCK_ABORT_END:
 
3445
                case TBLOCK_SUBABORT_END:
 
3446
                case TBLOCK_ABORT_PENDING:
 
3447
                case TBLOCK_SUBABORT_PENDING:
 
3448
                case TBLOCK_SUBRESTART:
 
3449
                case TBLOCK_SUBABORT_RESTART:
 
3450
                        elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
 
3451
                                 BlockStateAsString(s->blockState));
 
3452
                        break;
 
3453
        }
 
3454
 
 
3455
        CommitTransactionCommand();
 
3456
        StartTransactionCommand();
 
3457
}
 
3458
 
 
3459
/*
 
3460
 * ReleaseCurrentSubTransaction
 
3461
 *
 
3462
 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
 
3463
 * savepoint name (if any).
 
3464
 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
 
3465
 */
 
3466
void
 
3467
ReleaseCurrentSubTransaction(void)
 
3468
{
 
3469
        TransactionState s = CurrentTransactionState;
 
3470
 
 
3471
        if (s->blockState != TBLOCK_SUBINPROGRESS)
 
3472
                elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
 
3473
                         BlockStateAsString(s->blockState));
 
3474
        Assert(s->state == TRANS_INPROGRESS);
 
3475
        MemoryContextSwitchTo(CurTransactionContext);
 
3476
        CommitSubTransaction();
 
3477
        s = CurrentTransactionState;    /* changed by pop */
 
3478
        Assert(s->state == TRANS_INPROGRESS);
 
3479
}
 
3480
 
 
3481
/*
 
3482
 * RollbackAndReleaseCurrentSubTransaction
 
3483
 *
 
3484
 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
 
3485
 * of its savepoint name (if any).
 
3486
 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
 
3487
 */
 
3488
void
 
3489
RollbackAndReleaseCurrentSubTransaction(void)
 
3490
{
 
3491
        TransactionState s = CurrentTransactionState;
 
3492
 
 
3493
        switch (s->blockState)
 
3494
        {
 
3495
                        /* Must be in a subtransaction */
 
3496
                case TBLOCK_SUBINPROGRESS:
 
3497
                case TBLOCK_SUBABORT:
 
3498
                        break;
 
3499
 
 
3500
                        /* These cases are invalid. */
 
3501
                case TBLOCK_DEFAULT:
 
3502
                case TBLOCK_STARTED:
 
3503
                case TBLOCK_BEGIN:
 
3504
                case TBLOCK_SUBBEGIN:
 
3505
                case TBLOCK_INPROGRESS:
 
3506
                case TBLOCK_END:
 
3507
                case TBLOCK_SUBEND:
 
3508
                case TBLOCK_ABORT:
 
3509
                case TBLOCK_ABORT_END:
 
3510
                case TBLOCK_SUBABORT_END:
 
3511
                case TBLOCK_ABORT_PENDING:
 
3512
                case TBLOCK_SUBABORT_PENDING:
 
3513
                case TBLOCK_SUBRESTART:
 
3514
                case TBLOCK_SUBABORT_RESTART:
 
3515
                case TBLOCK_PREPARE:
 
3516
                        elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
 
3517
                                 BlockStateAsString(s->blockState));
 
3518
                        break;
 
3519
        }
 
3520
 
 
3521
        /*
 
3522
         * Abort the current subtransaction, if needed.
 
3523
         */
 
3524
        if (s->blockState == TBLOCK_SUBINPROGRESS)
 
3525
                AbortSubTransaction();
 
3526
 
 
3527
        /* And clean it up, too */
 
3528
        CleanupSubTransaction();
 
3529
 
 
3530
        s = CurrentTransactionState;    /* changed by pop */
 
3531
        AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
 
3532
                                s->blockState == TBLOCK_INPROGRESS ||
 
3533
                                s->blockState == TBLOCK_STARTED);
 
3534
}
 
3535
 
 
3536
/*
 
3537
 *      AbortOutOfAnyTransaction
 
3538
 *
 
3539
 *      This routine is provided for error recovery purposes.  It aborts any
 
3540
 *      active transaction or transaction block, leaving the system in a known
 
3541
 *      idle state.
 
3542
 */
 
3543
void
 
3544
AbortOutOfAnyTransaction(void)
 
3545
{
 
3546
        TransactionState s = CurrentTransactionState;
 
3547
 
 
3548
        /*
 
3549
         * Get out of any transaction or nested transaction
 
3550
         */
 
3551
        do
 
3552
        {
 
3553
                switch (s->blockState)
 
3554
                {
 
3555
                        case TBLOCK_DEFAULT:
 
3556
                                /* Not in a transaction, do nothing */
 
3557
                                break;
 
3558
                        case TBLOCK_STARTED:
 
3559
                        case TBLOCK_BEGIN:
 
3560
                        case TBLOCK_INPROGRESS:
 
3561
                        case TBLOCK_END:
 
3562
                        case TBLOCK_ABORT_PENDING:
 
3563
                        case TBLOCK_PREPARE:
 
3564
                                /* In a transaction, so clean up */
 
3565
                                AbortTransaction();
 
3566
                                CleanupTransaction();
 
3567
                                s->blockState = TBLOCK_DEFAULT;
 
3568
                                break;
 
3569
                        case TBLOCK_ABORT:
 
3570
                        case TBLOCK_ABORT_END:
 
3571
                                /* AbortTransaction already done, still need Cleanup */
 
3572
                                CleanupTransaction();
 
3573
                                s->blockState = TBLOCK_DEFAULT;
 
3574
                                break;
 
3575
 
 
3576
                                /*
 
3577
                                 * In a subtransaction, so clean it up and abort parent too
 
3578
                                 */
 
3579
                        case TBLOCK_SUBBEGIN:
 
3580
                        case TBLOCK_SUBINPROGRESS:
 
3581
                        case TBLOCK_SUBEND:
 
3582
                        case TBLOCK_SUBABORT_PENDING:
 
3583
                        case TBLOCK_SUBRESTART:
 
3584
                                AbortSubTransaction();
 
3585
                                CleanupSubTransaction();
 
3586
                                s = CurrentTransactionState;    /* changed by pop */
 
3587
                                break;
 
3588
 
 
3589
                        case TBLOCK_SUBABORT:
 
3590
                        case TBLOCK_SUBABORT_END:
 
3591
                        case TBLOCK_SUBABORT_RESTART:
 
3592
                                /* As above, but AbortSubTransaction already done */
 
3593
                                CleanupSubTransaction();
 
3594
                                s = CurrentTransactionState;    /* changed by pop */
 
3595
                                break;
 
3596
                }
 
3597
        } while (s->blockState != TBLOCK_DEFAULT);
 
3598
 
 
3599
        /* Should be out of all subxacts now */
 
3600
        Assert(s->parent == NULL);
 
3601
}
 
3602
 
 
3603
/*
 
3604
 * IsTransactionBlock --- are we within a transaction block?
 
3605
 */
 
3606
bool
 
3607
IsTransactionBlock(void)
 
3608
{
 
3609
        TransactionState s = CurrentTransactionState;
 
3610
 
 
3611
        if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
 
3612
                return false;
 
3613
 
 
3614
        return true;
 
3615
}
 
3616
 
 
3617
/*
 
3618
 * IsTransactionOrTransactionBlock --- are we within either a transaction
 
3619
 * or a transaction block?      (The backend is only really "idle" when this
 
3620
 * returns false.)
 
3621
 *
 
3622
 * This should match up with IsTransactionBlock and IsTransactionState.
 
3623
 */
 
3624
bool
 
3625
IsTransactionOrTransactionBlock(void)
 
3626
{
 
3627
        TransactionState s = CurrentTransactionState;
 
3628
 
 
3629
        if (s->blockState == TBLOCK_DEFAULT)
 
3630
                return false;
 
3631
 
 
3632
        return true;
 
3633
}
 
3634
 
 
3635
/*
 
3636
 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
 
3637
 */
 
3638
char
 
3639
TransactionBlockStatusCode(void)
 
3640
{
 
3641
        TransactionState s = CurrentTransactionState;
 
3642
 
 
3643
        switch (s->blockState)
 
3644
        {
 
3645
                case TBLOCK_DEFAULT:
 
3646
                case TBLOCK_STARTED:
 
3647
                        return 'I';                     /* idle --- not in transaction */
 
3648
                case TBLOCK_BEGIN:
 
3649
                case TBLOCK_SUBBEGIN:
 
3650
                case TBLOCK_INPROGRESS:
 
3651
                case TBLOCK_SUBINPROGRESS:
 
3652
                case TBLOCK_END:
 
3653
                case TBLOCK_SUBEND:
 
3654
                case TBLOCK_PREPARE:
 
3655
                        return 'T';                     /* in transaction */
 
3656
                case TBLOCK_ABORT:
 
3657
                case TBLOCK_SUBABORT:
 
3658
                case TBLOCK_ABORT_END:
 
3659
                case TBLOCK_SUBABORT_END:
 
3660
                case TBLOCK_ABORT_PENDING:
 
3661
                case TBLOCK_SUBABORT_PENDING:
 
3662
                case TBLOCK_SUBRESTART:
 
3663
                case TBLOCK_SUBABORT_RESTART:
 
3664
                        return 'E';                     /* in failed transaction */
 
3665
        }
 
3666
 
 
3667
        /* should never get here */
 
3668
        elog(FATAL, "invalid transaction block state: %s",
 
3669
                 BlockStateAsString(s->blockState));
 
3670
        return 0;                                       /* keep compiler quiet */
 
3671
}
 
3672
 
 
3673
/*
 
3674
 * IsSubTransaction
 
3675
 */
 
3676
bool
 
3677
IsSubTransaction(void)
 
3678
{
 
3679
        TransactionState s = CurrentTransactionState;
 
3680
 
 
3681
        if (s->nestingLevel >= 2)
 
3682
                return true;
 
3683
 
 
3684
        return false;
 
3685
}
 
3686
 
 
3687
/*
 
3688
 * StartSubTransaction
 
3689
 *
 
3690
 * If you're wondering why this is separate from PushTransaction: it's because
 
3691
 * we can't conveniently do this stuff right inside DefineSavepoint.  The
 
3692
 * SAVEPOINT utility command will be executed inside a Portal, and if we
 
3693
 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
 
3694
 * the Portal will undo those settings.  So we make DefineSavepoint just
 
3695
 * push a dummy transaction block, and when control returns to the main
 
3696
 * idle loop, CommitTransactionCommand will be called, and we'll come here
 
3697
 * to finish starting the subtransaction.
 
3698
 */
 
3699
static void
 
3700
StartSubTransaction(void)
 
3701
{
 
3702
        TransactionState s = CurrentTransactionState;
 
3703
 
 
3704
        if (s->state != TRANS_DEFAULT)
 
3705
                elog(WARNING, "StartSubTransaction while in %s state",
 
3706
                         TransStateAsString(s->state));
 
3707
 
 
3708
        s->state = TRANS_START;
 
3709
 
 
3710
        /*
 
3711
         * Initialize subsystems for new subtransaction
 
3712
         *
 
3713
         * must initialize resource-management stuff first
 
3714
         */
 
3715
        AtSubStart_Memory();
 
3716
        AtSubStart_ResourceOwner();
 
3717
        AtSubStart_Inval();
 
3718
        AtSubStart_Notify();
 
3719
        AfterTriggerBeginSubXact();
 
3720
 
 
3721
        s->state = TRANS_INPROGRESS;
 
3722
 
 
3723
        /*
 
3724
         * Call start-of-subxact callbacks
 
3725
         */
 
3726
        CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
 
3727
                                                 s->parent->subTransactionId);
 
3728
 
 
3729
        ShowTransactionState("StartSubTransaction");
 
3730
}
 
3731
 
 
3732
/*
 
3733
 * CommitSubTransaction
 
3734
 *
 
3735
 *      The caller has to make sure to always reassign CurrentTransactionState
 
3736
 *      if it has a local pointer to it after calling this function.
 
3737
 */
 
3738
static void
 
3739
CommitSubTransaction(void)
 
3740
{
 
3741
        TransactionState s = CurrentTransactionState;
 
3742
 
 
3743
        ShowTransactionState("CommitSubTransaction");
 
3744
 
 
3745
        if (s->state != TRANS_INPROGRESS)
 
3746
                elog(WARNING, "CommitSubTransaction while in %s state",
 
3747
                         TransStateAsString(s->state));
 
3748
 
 
3749
        /* Pre-commit processing goes here -- nothing to do at the moment */
 
3750
 
 
3751
        s->state = TRANS_COMMIT;
 
3752
 
 
3753
        /* Must CCI to ensure commands of subtransaction are seen as done */
 
3754
        CommandCounterIncrement();
 
3755
 
 
3756
        /* 
 
3757
         * Prior to 8.4 we marked subcommit in clog at this point.  We now only
 
3758
         * perform that step, if required, as part of the atomic update of the
 
3759
         * whole transaction tree at top level commit or abort.
 
3760
         */
 
3761
 
 
3762
        /* Post-commit cleanup */
 
3763
        if (TransactionIdIsValid(s->transactionId))
 
3764
                AtSubCommit_childXids();
 
3765
        AfterTriggerEndSubXact(true);
 
3766
        AtSubCommit_Portals(s->subTransactionId,
 
3767
                                                s->parent->subTransactionId,
 
3768
                                                s->parent->curTransactionOwner);
 
3769
        AtEOSubXact_LargeObject(true, s->subTransactionId,
 
3770
                                                        s->parent->subTransactionId);
 
3771
        AtSubCommit_Notify();
 
3772
        AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
 
3773
                                                                s->parent->subTransactionId);
 
3774
 
 
3775
        CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
 
3776
                                                 s->parent->subTransactionId);
 
3777
 
 
3778
        ResourceOwnerRelease(s->curTransactionOwner,
 
3779
                                                 RESOURCE_RELEASE_BEFORE_LOCKS,
 
3780
                                                 true, false);
 
3781
        AtEOSubXact_RelationCache(true, s->subTransactionId,
 
3782
                                                          s->parent->subTransactionId);
 
3783
        AtEOSubXact_Inval(true);
 
3784
        AtSubCommit_smgr();
 
3785
 
 
3786
        /*
 
3787
         * The only lock we actually release here is the subtransaction XID lock.
 
3788
         * The rest just get transferred to the parent resource owner.
 
3789
         */
 
3790
        CurrentResourceOwner = s->curTransactionOwner;
 
3791
        if (TransactionIdIsValid(s->transactionId))
 
3792
                XactLockTableDelete(s->transactionId);
 
3793
 
 
3794
        ResourceOwnerRelease(s->curTransactionOwner,
 
3795
                                                 RESOURCE_RELEASE_LOCKS,
 
3796
                                                 true, false);
 
3797
        ResourceOwnerRelease(s->curTransactionOwner,
 
3798
                                                 RESOURCE_RELEASE_AFTER_LOCKS,
 
3799
                                                 true, false);
 
3800
 
 
3801
        AtEOXact_GUC(true, s->gucNestLevel);
 
3802
        AtEOSubXact_SPI(true, s->subTransactionId);
 
3803
        AtEOSubXact_on_commit_actions(true, s->subTransactionId,
 
3804
                                                                  s->parent->subTransactionId);
 
3805
        AtEOSubXact_Namespace(true, s->subTransactionId,
 
3806
                                                  s->parent->subTransactionId);
 
3807
        AtEOSubXact_Files(true, s->subTransactionId,
 
3808
                                          s->parent->subTransactionId);
 
3809
        AtEOSubXact_HashTables(true, s->nestingLevel);
 
3810
        AtEOSubXact_PgStat(true, s->nestingLevel);
 
3811
        AtSubCommit_Snapshot(s->nestingLevel);
 
3812
 
 
3813
        /*
 
3814
         * We need to restore the upper transaction's read-only state, in case the
 
3815
         * upper is read-write while the child is read-only; GUC will incorrectly
 
3816
         * think it should leave the child state in place.
 
3817
         */
 
3818
        XactReadOnly = s->prevXactReadOnly;
 
3819
 
 
3820
        CurrentResourceOwner = s->parent->curTransactionOwner;
 
3821
        CurTransactionResourceOwner = s->parent->curTransactionOwner;
 
3822
        ResourceOwnerDelete(s->curTransactionOwner);
 
3823
        s->curTransactionOwner = NULL;
 
3824
 
 
3825
        AtSubCommit_Memory();
 
3826
 
 
3827
        s->state = TRANS_DEFAULT;
 
3828
 
 
3829
        PopTransaction();
 
3830
}
 
3831
 
 
3832
/*
 
3833
 * AbortSubTransaction
 
3834
 */
 
3835
static void
 
3836
AbortSubTransaction(void)
 
3837
{
 
3838
        TransactionState s = CurrentTransactionState;
 
3839
 
 
3840
        /* Prevent cancel/die interrupt while cleaning up */
 
3841
        HOLD_INTERRUPTS();
 
3842
 
 
3843
        /* Make sure we have a valid memory context and resource owner */
 
3844
        AtSubAbort_Memory();
 
3845
        AtSubAbort_ResourceOwner();
 
3846
 
 
3847
        /*
 
3848
         * Release any LW locks we might be holding as quickly as possible.
 
3849
         * (Regular locks, however, must be held till we finish aborting.)
 
3850
         * Releasing LW locks is critical since we might try to grab them again
 
3851
         * while cleaning up!
 
3852
         *
 
3853
         * FIXME This may be incorrect --- Are there some locks we should keep?
 
3854
         * Buffer locks, for example?  I don't think so but I'm not sure.
 
3855
         */
 
3856
        LWLockReleaseAll();
 
3857
 
 
3858
        AbortBufferIO();
 
3859
        UnlockBuffers();
 
3860
 
 
3861
        LockWaitCancel();
 
3862
 
 
3863
        /*
 
3864
         * check the current transaction state
 
3865
         */
 
3866
        ShowTransactionState("AbortSubTransaction");
 
3867
 
 
3868
        if (s->state != TRANS_INPROGRESS)
 
3869
                elog(WARNING, "AbortSubTransaction while in %s state",
 
3870
                         TransStateAsString(s->state));
 
3871
 
 
3872
        s->state = TRANS_ABORT;
 
3873
 
 
3874
        /*
 
3875
         * Reset user ID which might have been changed transiently.  (See notes
 
3876
         * in AbortTransaction.)
 
3877
         */
 
3878
        SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
 
3879
 
 
3880
        /*
 
3881
         * We can skip all this stuff if the subxact failed before creating a
 
3882
         * ResourceOwner...
 
3883
         */
 
3884
        if (s->curTransactionOwner)
 
3885
        {
 
3886
                AfterTriggerEndSubXact(false);
 
3887
                AtSubAbort_Portals(s->subTransactionId,
 
3888
                                                   s->parent->subTransactionId,
 
3889
                                                   s->parent->curTransactionOwner);
 
3890
                AtEOSubXact_LargeObject(false, s->subTransactionId,
 
3891
                                                                s->parent->subTransactionId);
 
3892
                AtSubAbort_Notify();
 
3893
                AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
 
3894
                                                                        s->parent->subTransactionId);
 
3895
 
 
3896
                /* Advertise the fact that we aborted in pg_clog. */
 
3897
                (void) RecordTransactionAbort(true);
 
3898
 
 
3899
                /* Post-abort cleanup */
 
3900
                if (TransactionIdIsValid(s->transactionId))
 
3901
                        AtSubAbort_childXids();
 
3902
 
 
3903
                CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
 
3904
                                                         s->parent->subTransactionId);
 
3905
 
 
3906
                ResourceOwnerRelease(s->curTransactionOwner,
 
3907
                                                         RESOURCE_RELEASE_BEFORE_LOCKS,
 
3908
                                                         false, false);
 
3909
                AtEOSubXact_RelationCache(false, s->subTransactionId,
 
3910
                                                                  s->parent->subTransactionId);
 
3911
                AtEOSubXact_Inval(false);
 
3912
                AtSubAbort_smgr();
 
3913
                ResourceOwnerRelease(s->curTransactionOwner,
 
3914
                                                         RESOURCE_RELEASE_LOCKS,
 
3915
                                                         false, false);
 
3916
                ResourceOwnerRelease(s->curTransactionOwner,
 
3917
                                                         RESOURCE_RELEASE_AFTER_LOCKS,
 
3918
                                                         false, false);
 
3919
 
 
3920
                AtEOXact_GUC(false, s->gucNestLevel);
 
3921
                AtEOSubXact_SPI(false, s->subTransactionId);
 
3922
                AtEOXact_xml();
 
3923
                AtEOSubXact_on_commit_actions(false, s->subTransactionId,
 
3924
                                                                          s->parent->subTransactionId);
 
3925
                AtEOSubXact_Namespace(false, s->subTransactionId,
 
3926
                                                          s->parent->subTransactionId);
 
3927
                AtEOSubXact_Files(false, s->subTransactionId,
 
3928
                                                  s->parent->subTransactionId);
 
3929
                AtEOSubXact_HashTables(false, s->nestingLevel);
 
3930
                AtEOSubXact_PgStat(false, s->nestingLevel);
 
3931
                AtSubAbort_Snapshot(s->nestingLevel);
 
3932
        }
 
3933
 
 
3934
        /*
 
3935
         * Restore the upper transaction's read-only state, too.  This should be
 
3936
         * redundant with GUC's cleanup but we may as well do it for consistency
 
3937
         * with the commit case.
 
3938
         */
 
3939
        XactReadOnly = s->prevXactReadOnly;
 
3940
 
 
3941
        RESUME_INTERRUPTS();
 
3942
}
 
3943
 
 
3944
/*
 
3945
 * CleanupSubTransaction
 
3946
 *
 
3947
 *      The caller has to make sure to always reassign CurrentTransactionState
 
3948
 *      if it has a local pointer to it after calling this function.
 
3949
 */
 
3950
static void
 
3951
CleanupSubTransaction(void)
 
3952
{
 
3953
        TransactionState s = CurrentTransactionState;
 
3954
 
 
3955
        ShowTransactionState("CleanupSubTransaction");
 
3956
 
 
3957
        if (s->state != TRANS_ABORT)
 
3958
                elog(WARNING, "CleanupSubTransaction while in %s state",
 
3959
                         TransStateAsString(s->state));
 
3960
 
 
3961
        AtSubCleanup_Portals(s->subTransactionId);
 
3962
 
 
3963
        CurrentResourceOwner = s->parent->curTransactionOwner;
 
3964
        CurTransactionResourceOwner = s->parent->curTransactionOwner;
 
3965
        if (s->curTransactionOwner)
 
3966
                ResourceOwnerDelete(s->curTransactionOwner);
 
3967
        s->curTransactionOwner = NULL;
 
3968
 
 
3969
        AtSubCleanup_Memory();
 
3970
 
 
3971
        s->state = TRANS_DEFAULT;
 
3972
 
 
3973
        PopTransaction();
 
3974
}
 
3975
 
 
3976
/*
 
3977
 * PushTransaction
 
3978
 *              Create transaction state stack entry for a subtransaction
 
3979
 *
 
3980
 *      The caller has to make sure to always reassign CurrentTransactionState
 
3981
 *      if it has a local pointer to it after calling this function.
 
3982
 */
 
3983
static void
 
3984
PushTransaction(void)
 
3985
{
 
3986
        TransactionState p = CurrentTransactionState;
 
3987
        TransactionState s;
 
3988
 
 
3989
        /*
 
3990
         * We keep subtransaction state nodes in TopTransactionContext.
 
3991
         */
 
3992
        s = (TransactionState)
 
3993
                MemoryContextAllocZero(TopTransactionContext,
 
3994
                                                           sizeof(TransactionStateData));
 
3995
 
 
3996
        /*
 
3997
         * Assign a subtransaction ID, watching out for counter wraparound.
 
3998
         */
 
3999
        currentSubTransactionId += 1;
 
4000
        if (currentSubTransactionId == InvalidSubTransactionId)
 
4001
        {
 
4002
                currentSubTransactionId -= 1;
 
4003
                pfree(s);
 
4004
                ereport(ERROR,
 
4005
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 
4006
                                 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
 
4007
        }
 
4008
 
 
4009
        /*
 
4010
         * We can now stack a minimally valid subtransaction without fear of
 
4011
         * failure.
 
4012
         */
 
4013
        s->transactionId = InvalidTransactionId;        /* until assigned */
 
4014
        s->subTransactionId = currentSubTransactionId;
 
4015
        s->parent = p;
 
4016
        s->nestingLevel = p->nestingLevel + 1;
 
4017
        s->gucNestLevel = NewGUCNestLevel();
 
4018
        s->savepointLevel = p->savepointLevel;
 
4019
        s->state = TRANS_DEFAULT;
 
4020
        s->blockState = TBLOCK_SUBBEGIN;
 
4021
        GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
 
4022
        s->prevXactReadOnly = XactReadOnly;
 
4023
 
 
4024
        CurrentTransactionState = s;
 
4025
 
 
4026
        /*
 
4027
         * AbortSubTransaction and CleanupSubTransaction have to be able to cope
 
4028
         * with the subtransaction from here on out; in particular they should not
 
4029
         * assume that it necessarily has a transaction context, resource owner,
 
4030
         * or XID.
 
4031
         */
 
4032
}
 
4033
 
 
4034
/*
 
4035
 * PopTransaction
 
4036
 *              Pop back to parent transaction state
 
4037
 *
 
4038
 *      The caller has to make sure to always reassign CurrentTransactionState
 
4039
 *      if it has a local pointer to it after calling this function.
 
4040
 */
 
4041
static void
 
4042
PopTransaction(void)
 
4043
{
 
4044
        TransactionState s = CurrentTransactionState;
 
4045
 
 
4046
        if (s->state != TRANS_DEFAULT)
 
4047
                elog(WARNING, "PopTransaction while in %s state",
 
4048
                         TransStateAsString(s->state));
 
4049
 
 
4050
        if (s->parent == NULL)
 
4051
                elog(FATAL, "PopTransaction with no parent");
 
4052
 
 
4053
        CurrentTransactionState = s->parent;
 
4054
 
 
4055
        /* Let's just make sure CurTransactionContext is good */
 
4056
        CurTransactionContext = s->parent->curTransactionContext;
 
4057
        MemoryContextSwitchTo(CurTransactionContext);
 
4058
 
 
4059
        /* Ditto for ResourceOwner links */
 
4060
        CurTransactionResourceOwner = s->parent->curTransactionOwner;
 
4061
        CurrentResourceOwner = s->parent->curTransactionOwner;
 
4062
 
 
4063
        /* Free the old child structure */
 
4064
        if (s->name)
 
4065
                pfree(s->name);
 
4066
        pfree(s);
 
4067
}
 
4068
 
 
4069
/*
 
4070
 * ShowTransactionState
 
4071
 *              Debug support
 
4072
 */
 
4073
static void
 
4074
ShowTransactionState(const char *str)
 
4075
{
 
4076
        /* skip work if message will definitely not be printed */
 
4077
        if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
 
4078
        {
 
4079
                elog(DEBUG3, "%s", str);
 
4080
                ShowTransactionStateRec(CurrentTransactionState);
 
4081
        }
 
4082
}
 
4083
 
 
4084
/*
 
4085
 * ShowTransactionStateRec
 
4086
 *              Recursive subroutine for ShowTransactionState
 
4087
 */
 
4088
static void
 
4089
ShowTransactionStateRec(TransactionState s)
 
4090
{
 
4091
        StringInfoData buf;
 
4092
 
 
4093
        initStringInfo(&buf);
 
4094
 
 
4095
        if (s->nChildXids > 0)
 
4096
        {
 
4097
                int i;
 
4098
 
 
4099
                appendStringInfo(&buf, "%u", s->childXids[0]);
 
4100
                for (i = 1; i < s->nChildXids; i++)
 
4101
                        appendStringInfo(&buf, " %u", s->childXids[i]);
 
4102
        }
 
4103
 
 
4104
        if (s->parent)
 
4105
                ShowTransactionStateRec(s->parent);
 
4106
 
 
4107
        /* use ereport to suppress computation if msg will not be printed */
 
4108
        ereport(DEBUG3,
 
4109
                        (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
 
4110
                                                         PointerIsValid(s->name) ? s->name : "unnamed",
 
4111
                                                         BlockStateAsString(s->blockState),
 
4112
                                                         TransStateAsString(s->state),
 
4113
                                                         (unsigned int) s->transactionId,
 
4114
                                                         (unsigned int) s->subTransactionId,
 
4115
                                                         (unsigned int) currentCommandId,
 
4116
                                                         currentCommandIdUsed ? " (used)" : "",
 
4117
                                                         s->nestingLevel, buf.data)));
 
4118
 
 
4119
        pfree(buf.data);
 
4120
}
 
4121
 
 
4122
/*
 
4123
 * BlockStateAsString
 
4124
 *              Debug support
 
4125
 */
 
4126
static const char *
 
4127
BlockStateAsString(TBlockState blockState)
 
4128
{
 
4129
        switch (blockState)
 
4130
        {
 
4131
                case TBLOCK_DEFAULT:
 
4132
                        return "DEFAULT";
 
4133
                case TBLOCK_STARTED:
 
4134
                        return "STARTED";
 
4135
                case TBLOCK_BEGIN:
 
4136
                        return "BEGIN";
 
4137
                case TBLOCK_INPROGRESS:
 
4138
                        return "INPROGRESS";
 
4139
                case TBLOCK_END:
 
4140
                        return "END";
 
4141
                case TBLOCK_ABORT:
 
4142
                        return "ABORT";
 
4143
                case TBLOCK_ABORT_END:
 
4144
                        return "ABORT END";
 
4145
                case TBLOCK_ABORT_PENDING:
 
4146
                        return "ABORT PEND";
 
4147
                case TBLOCK_PREPARE:
 
4148
                        return "PREPARE";
 
4149
                case TBLOCK_SUBBEGIN:
 
4150
                        return "SUB BEGIN";
 
4151
                case TBLOCK_SUBINPROGRESS:
 
4152
                        return "SUB INPROGRS";
 
4153
                case TBLOCK_SUBEND:
 
4154
                        return "SUB END";
 
4155
                case TBLOCK_SUBABORT:
 
4156
                        return "SUB ABORT";
 
4157
                case TBLOCK_SUBABORT_END:
 
4158
                        return "SUB ABORT END";
 
4159
                case TBLOCK_SUBABORT_PENDING:
 
4160
                        return "SUB ABRT PEND";
 
4161
                case TBLOCK_SUBRESTART:
 
4162
                        return "SUB RESTART";
 
4163
                case TBLOCK_SUBABORT_RESTART:
 
4164
                        return "SUB AB RESTRT";
 
4165
        }
 
4166
        return "UNRECOGNIZED";
 
4167
}
 
4168
 
 
4169
/*
 
4170
 * TransStateAsString
 
4171
 *              Debug support
 
4172
 */
 
4173
static const char *
 
4174
TransStateAsString(TransState state)
 
4175
{
 
4176
        switch (state)
 
4177
        {
 
4178
                case TRANS_DEFAULT:
 
4179
                        return "DEFAULT";
 
4180
                case TRANS_START:
 
4181
                        return "START";
 
4182
                case TRANS_INPROGRESS:
 
4183
                        return "INPROGR";
 
4184
                case TRANS_COMMIT:
 
4185
                        return "COMMIT";
 
4186
                case TRANS_ABORT:
 
4187
                        return "ABORT";
 
4188
                case TRANS_PREPARE:
 
4189
                        return "PREPARE";
 
4190
        }
 
4191
        return "UNRECOGNIZED";
 
4192
}
 
4193
 
 
4194
/*
 
4195
 * xactGetCommittedChildren
 
4196
 *
 
4197
 * Gets the list of committed children of the current transaction.      The return
 
4198
 * value is the number of child transactions.  *ptr is set to point to an
 
4199
 * array of TransactionIds.  The array is allocated in TopTransactionContext;
 
4200
 * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
 
4201
 * If there are no subxacts, *ptr is set to NULL.
 
4202
 */
 
4203
int
 
4204
xactGetCommittedChildren(TransactionId **ptr)
 
4205
{
 
4206
        TransactionState s = CurrentTransactionState;
 
4207
 
 
4208
        if (s->nChildXids == 0)
 
4209
                *ptr = NULL;
 
4210
        else
 
4211
                *ptr = s->childXids;
 
4212
 
 
4213
        return s->nChildXids;
 
4214
}
 
4215
 
 
4216
/*
 
4217
 *      XLOG support routines
 
4218
 */
 
4219
 
 
4220
static void
 
4221
xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
 
4222
{
 
4223
        TransactionId *sub_xids;
 
4224
        TransactionId max_xid;
 
4225
        int                     i;
 
4226
 
 
4227
        /* Mark the transaction committed in pg_clog */
 
4228
        sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
 
4229
        TransactionIdCommitTree(xid, xlrec->nsubxacts, sub_xids);
 
4230
 
 
4231
        /* Make sure nextXid is beyond any XID mentioned in the record */
 
4232
        max_xid = xid;
 
4233
        for (i = 0; i < xlrec->nsubxacts; i++)
 
4234
        {
 
4235
                if (TransactionIdPrecedes(max_xid, sub_xids[i]))
 
4236
                        max_xid = sub_xids[i];
 
4237
        }
 
4238
        if (TransactionIdFollowsOrEquals(max_xid,
 
4239
                                                                         ShmemVariableCache->nextXid))
 
4240
        {
 
4241
                ShmemVariableCache->nextXid = max_xid;
 
4242
                TransactionIdAdvance(ShmemVariableCache->nextXid);
 
4243
        }
 
4244
 
 
4245
        /* Make sure files supposed to be dropped are dropped */
 
4246
        for (i = 0; i < xlrec->nrels; i++)
 
4247
        {
 
4248
                SMgrRelation srel = smgropen(xlrec->xnodes[i]);
 
4249
                ForkNumber fork;
 
4250
 
 
4251
                for (fork = 0; fork <= MAX_FORKNUM; fork++)
 
4252
                {
 
4253
                        if (smgrexists(srel, fork))
 
4254
                        {
 
4255
                                XLogDropRelation(xlrec->xnodes[i], fork);
 
4256
                                smgrdounlink(srel, fork, false, true);
 
4257
                        }
 
4258
                }
 
4259
                smgrclose(srel);
 
4260
        }
 
4261
}
 
4262
 
 
4263
static void
 
4264
xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
 
4265
{
 
4266
        TransactionId *sub_xids;
 
4267
        TransactionId max_xid;
 
4268
        int                     i;
 
4269
 
 
4270
        /* Mark the transaction aborted in pg_clog */
 
4271
        sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
 
4272
        TransactionIdAbortTree(xid, xlrec->nsubxacts, sub_xids);
 
4273
 
 
4274
        /* Make sure nextXid is beyond any XID mentioned in the record */
 
4275
        max_xid = xid;
 
4276
        for (i = 0; i < xlrec->nsubxacts; i++)
 
4277
        {
 
4278
                if (TransactionIdPrecedes(max_xid, sub_xids[i]))
 
4279
                        max_xid = sub_xids[i];
 
4280
        }
 
4281
        if (TransactionIdFollowsOrEquals(max_xid,
 
4282
                                                                         ShmemVariableCache->nextXid))
 
4283
        {
 
4284
                ShmemVariableCache->nextXid = max_xid;
 
4285
                TransactionIdAdvance(ShmemVariableCache->nextXid);
 
4286
        }
 
4287
 
 
4288
        /* Make sure files supposed to be dropped are dropped */
 
4289
        for (i = 0; i < xlrec->nrels; i++)
 
4290
        {
 
4291
                SMgrRelation srel = smgropen(xlrec->xnodes[i]);
 
4292
                ForkNumber fork;
 
4293
 
 
4294
                for (fork = 0; fork <= MAX_FORKNUM; fork++)
 
4295
                {
 
4296
                        if (smgrexists(srel, fork))
 
4297
                        {
 
4298
                                XLogDropRelation(xlrec->xnodes[i], fork);
 
4299
                                smgrdounlink(srel, fork, false, true);
 
4300
                        }
 
4301
                }
 
4302
                smgrclose(srel);
 
4303
        }
 
4304
}
 
4305
 
 
4306
void
 
4307
xact_redo(XLogRecPtr lsn, XLogRecord *record)
 
4308
{
 
4309
        uint8           info = record->xl_info & ~XLR_INFO_MASK;
 
4310
 
 
4311
        /* Backup blocks are not used in xact records */
 
4312
        Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
 
4313
 
 
4314
        if (info == XLOG_XACT_COMMIT)
 
4315
        {
 
4316
                xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
 
4317
 
 
4318
                xact_redo_commit(xlrec, record->xl_xid);
 
4319
        }
 
4320
        else if (info == XLOG_XACT_ABORT)
 
4321
        {
 
4322
                xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
 
4323
 
 
4324
                xact_redo_abort(xlrec, record->xl_xid);
 
4325
        }
 
4326
        else if (info == XLOG_XACT_PREPARE)
 
4327
        {
 
4328
                /* the record contents are exactly the 2PC file */
 
4329
                RecreateTwoPhaseFile(record->xl_xid,
 
4330
                                                         XLogRecGetData(record), record->xl_len);
 
4331
        }
 
4332
        else if (info == XLOG_XACT_COMMIT_PREPARED)
 
4333
        {
 
4334
                xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
 
4335
 
 
4336
                xact_redo_commit(&xlrec->crec, xlrec->xid);
 
4337
                RemoveTwoPhaseFile(xlrec->xid, false);
 
4338
        }
 
4339
        else if (info == XLOG_XACT_ABORT_PREPARED)
 
4340
        {
 
4341
                xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
 
4342
 
 
4343
                xact_redo_abort(&xlrec->arec, xlrec->xid);
 
4344
                RemoveTwoPhaseFile(xlrec->xid, false);
 
4345
        }
 
4346
        else
 
4347
                elog(PANIC, "xact_redo: unknown op code %u", info);
 
4348
}
 
4349
 
 
4350
static void
 
4351
xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
 
4352
{
 
4353
        int                     i;
 
4354
 
 
4355
        appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
 
4356
        if (xlrec->nrels > 0)
 
4357
        {
 
4358
                appendStringInfo(buf, "; rels:");
 
4359
                for (i = 0; i < xlrec->nrels; i++)
 
4360
                {
 
4361
                        char *path = relpath(xlrec->xnodes[i], MAIN_FORKNUM);
 
4362
                        appendStringInfo(buf, " %s", path);
 
4363
                        pfree(path);
 
4364
                }
 
4365
        }
 
4366
        if (xlrec->nsubxacts > 0)
 
4367
        {
 
4368
                TransactionId *xacts = (TransactionId *)
 
4369
                &xlrec->xnodes[xlrec->nrels];
 
4370
 
 
4371
                appendStringInfo(buf, "; subxacts:");
 
4372
                for (i = 0; i < xlrec->nsubxacts; i++)
 
4373
                        appendStringInfo(buf, " %u", xacts[i]);
 
4374
        }
 
4375
}
 
4376
 
 
4377
static void
 
4378
xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
 
4379
{
 
4380
        int                     i;
 
4381
 
 
4382
        appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
 
4383
        if (xlrec->nrels > 0)
 
4384
        {
 
4385
                appendStringInfo(buf, "; rels:");
 
4386
                for (i = 0; i < xlrec->nrels; i++)
 
4387
                {
 
4388
                        char *path = relpath(xlrec->xnodes[i], MAIN_FORKNUM);
 
4389
                        appendStringInfo(buf, " %s", path);
 
4390
                        pfree(path);
 
4391
                }
 
4392
        }
 
4393
        if (xlrec->nsubxacts > 0)
 
4394
        {
 
4395
                TransactionId *xacts = (TransactionId *)
 
4396
                &xlrec->xnodes[xlrec->nrels];
 
4397
 
 
4398
                appendStringInfo(buf, "; subxacts:");
 
4399
                for (i = 0; i < xlrec->nsubxacts; i++)
 
4400
                        appendStringInfo(buf, " %u", xacts[i]);
 
4401
        }
 
4402
}
 
4403
 
 
4404
void
 
4405
xact_desc(StringInfo buf, uint8 xl_info, char *rec)
 
4406
{
 
4407
        uint8           info = xl_info & ~XLR_INFO_MASK;
 
4408
 
 
4409
        if (info == XLOG_XACT_COMMIT)
 
4410
        {
 
4411
                xl_xact_commit *xlrec = (xl_xact_commit *) rec;
 
4412
 
 
4413
                appendStringInfo(buf, "commit: ");
 
4414
                xact_desc_commit(buf, xlrec);
 
4415
        }
 
4416
        else if (info == XLOG_XACT_ABORT)
 
4417
        {
 
4418
                xl_xact_abort *xlrec = (xl_xact_abort *) rec;
 
4419
 
 
4420
                appendStringInfo(buf, "abort: ");
 
4421
                xact_desc_abort(buf, xlrec);
 
4422
        }
 
4423
        else if (info == XLOG_XACT_PREPARE)
 
4424
        {
 
4425
                appendStringInfo(buf, "prepare");
 
4426
        }
 
4427
        else if (info == XLOG_XACT_COMMIT_PREPARED)
 
4428
        {
 
4429
                xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
 
4430
 
 
4431
                appendStringInfo(buf, "commit %u: ", xlrec->xid);
 
4432
                xact_desc_commit(buf, &xlrec->crec);
 
4433
        }
 
4434
        else if (info == XLOG_XACT_ABORT_PREPARED)
 
4435
        {
 
4436
                xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
 
4437
 
 
4438
                appendStringInfo(buf, "abort %u: ", xlrec->xid);
 
4439
                xact_desc_abort(buf, &xlrec->arec);
 
4440
        }
 
4441
        else
 
4442
                appendStringInfo(buf, "UNKNOWN");
 
4443
}