OSDN Git Service

Fix bad interaction between NOTIFY processing and V3 extended query
[pg-rex/syncrep.git] / src / backend / access / transam / xact.c
1 /*-------------------------------------------------------------------------
2  *
3  * xact.c
4  *        top level transaction system support routines
5  *
6  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.156 2003/10/16 16:50:41 tgl Exp $
12  *
13  * NOTES
14  *              Transaction aborts can now occur two ways:
15  *
16  *              1)      system dies from some internal cause  (syntax error, etc..)
17  *              2)      user types ABORT
18  *
19  *              These two cases used to be treated identically, but now
20  *              we need to distinguish them.  Why?      consider the following
21  *              two situations:
22  *
23  *                              case 1                                                  case 2
24  *                              ------                                                  ------
25  *              1) user types BEGIN                             1) user types BEGIN
26  *              2) user does something                  2) user does something
27  *              3) user does not like what              3) system aborts for some reason
28  *                 she sees and types ABORT
29  *
30  *              In case 1, we want to abort the transaction and return to the
31  *              default state.  In case 2, there may be more commands coming
32  *              our way which are part of the same transaction block and we have
33  *              to ignore these commands until we see a COMMIT transaction or
34  *              ROLLBACK.
35  *
36  *              Internal aborts are now handled by AbortTransactionBlock(), just as
37  *              they always have been, and user aborts are now handled by
38  *              UserAbortTransactionBlock().  Both of them rely on AbortTransaction()
39  *              to do all the real work.  The only difference is what state we
40  *              enter after AbortTransaction() does its work:
41  *
42  *              * AbortTransactionBlock() leaves us in TBLOCK_ABORT and
43  *              * UserAbortTransactionBlock() leaves us in TBLOCK_ENDABORT
44  *
45  *              Low-level transaction abort handling is divided into two phases:
46  *              * AbortTransaction() executes as soon as we realize the transaction
47  *                has failed.  It should release all shared resources (locks etc)
48  *                so that we do not delay other backends unnecessarily.
49  *              * CleanupTransaction() executes when we finally see a user COMMIT
50  *                or ROLLBACK command; it cleans things up and gets us out of
51  *                the transaction internally.  In particular, we mustn't destroy
52  *                TopTransactionContext until this point.
53  *
54  *       NOTES
55  *              The essential aspects of the transaction system are:
56  *
57  *                              o  transaction id generation
58  *                              o  transaction log updating
59  *                              o  memory cleanup
60  *                              o  cache invalidation
61  *                              o  lock cleanup
62  *
63  *              Hence, the functional division of the transaction code is
64  *              based on which of the above things need to be done during
65  *              a start/commit/abort transaction.  For instance, the
66  *              routine AtCommit_Memory() takes care of all the memory
67  *              cleanup stuff done at commit time.
68  *
69  *              The code is layered as follows:
70  *
71  *                              StartTransaction
72  *                              CommitTransaction
73  *                              AbortTransaction
74  *                              CleanupTransaction
75  *
76  *              are provided to do the lower level work like recording
77  *              the transaction status in the log and doing memory cleanup.
78  *              above these routines are another set of functions:
79  *
80  *                              StartTransactionCommand
81  *                              CommitTransactionCommand
82  *                              AbortCurrentTransaction
83  *
84  *              These are the routines used in the postgres main processing
85  *              loop.  They are sensitive to the current transaction block state
86  *              and make calls to the lower level routines appropriately.
87  *
88  *              Support for transaction blocks is provided via the functions:
89  *
90  *                              StartTransactionBlock
91  *                              CommitTransactionBlock
92  *                              AbortTransactionBlock
93  *
94  *              These are invoked only in response to a user "BEGIN WORK", "COMMIT",
95  *              or "ROLLBACK" command.  The tricky part about these functions
96  *              is that they are called within the postgres main loop, in between
97  *              the StartTransactionCommand() and CommitTransactionCommand().
98  *
99  *              For example, consider the following sequence of user commands:
100  *
101  *              1)              begin
102  *              2)              select * from foo
103  *              3)              insert into foo (bar = baz)
104  *              4)              commit
105  *
106  *              in the main processing loop, this results in the following
107  *              transaction sequence:
108  *
109  *                      /       StartTransactionCommand();
110  *              1) /    ProcessUtility();                               << begin
111  *                 \            StartTransactionBlock();
112  *                      \       CommitTransactionCommand();
113  *
114  *                      /       StartTransactionCommand();
115  *              2) <    ProcessQuery();                                 << select * from foo
116  *                      \       CommitTransactionCommand();
117  *
118  *                      /       StartTransactionCommand();
119  *              3) <    ProcessQuery();                                 << insert into foo (bar = baz)
120  *                      \       CommitTransactionCommand();
121  *
122  *                      /       StartTransactionCommand();
123  *              4) /    ProcessUtility();                               << commit
124  *                 \            CommitTransactionBlock();
125  *                      \       CommitTransactionCommand();
126  *
127  *              The point of this example is to demonstrate the need for
128  *              StartTransactionCommand() and CommitTransactionCommand() to
129  *              be state smart -- they should do nothing in between the calls
130  *              to StartTransactionBlock() and EndTransactionBlock() and
131  *              outside these calls they need to do normal start/commit
132  *              processing.
133  *
134  *              Furthermore, suppose the "select * from foo" caused an abort
135  *              condition.      We would then want to abort the transaction and
136  *              ignore all subsequent commands up to the "commit".
137  *              -cim 3/23/90
138  *
139  *-------------------------------------------------------------------------
140  */
141
142 #include "postgres.h"
143
144 #include <unistd.h>
145 #include <sys/time.h>
146
147 #include "access/gistscan.h"
148 #include "access/hash.h"
149 #include "access/nbtree.h"
150 #include "access/rtree.h"
151 #include "access/xact.h"
152 #include "catalog/heap.h"
153 #include "catalog/index.h"
154 #include "catalog/namespace.h"
155 #include "commands/async.h"
156 #include "commands/tablecmds.h"
157 #include "commands/trigger.h"
158 #include "commands/user.h"
159 #include "executor/spi.h"
160 #include "libpq/be-fsstubs.h"
161 #include "miscadmin.h"
162 #include "storage/proc.h"
163 #include "storage/sinval.h"
164 #include "storage/smgr.h"
165 #include "utils/guc.h"
166 #include "utils/inval.h"
167 #include "utils/memutils.h"
168 #include "utils/portal.h"
169 #include "utils/catcache.h"
170 #include "utils/relcache.h"
171 #include "pgstat.h"
172
173
174 static void AbortTransaction(void);
175 static void AtAbort_Cache(void);
176 static void AtAbort_Locks(void);
177 static void AtAbort_Memory(void);
178 static void AtCleanup_Memory(void);
179 static void AtCommit_Cache(void);
180 static void AtCommit_LocalCache(void);
181 static void AtCommit_Locks(void);
182 static void AtCommit_Memory(void);
183 static void AtStart_Cache(void);
184 static void AtStart_Locks(void);
185 static void AtStart_Memory(void);
186 static void CallEOXactCallbacks(bool isCommit);
187 static void CleanupTransaction(void);
188 static void CommitTransaction(void);
189 static void RecordTransactionAbort(void);
190 static void StartTransaction(void);
191
192 /*
193  *      global variables holding the current transaction state.
194  */
195 static TransactionStateData CurrentTransactionStateData = {
196         0,                                                      /* transaction id */
197         FirstCommandId,                         /* command id */
198         0,                                                      /* scan command id */
199         0x0,                                            /* start time */
200         TRANS_DEFAULT,                          /* transaction state */
201         TBLOCK_DEFAULT                          /* transaction block state from the client
202                                                                  * perspective */
203 };
204
205 static TransactionState CurrentTransactionState = &CurrentTransactionStateData;
206
207 /*
208  *      User-tweakable parameters
209  */
210 int                     DefaultXactIsoLevel = XACT_READ_COMMITTED;
211 int                     XactIsoLevel;
212
213 bool            DefaultXactReadOnly = false;
214 bool            XactReadOnly;
215
216 int                     CommitDelay = 0;        /* precommit delay in microseconds */
217 int                     CommitSiblings = 5; /* number of concurrent xacts needed to
218                                                                  * sleep */
219
220
221 /*
222  * List of add-on end-of-xact callbacks
223  */
224 typedef struct EOXactCallbackItem
225 {
226         struct EOXactCallbackItem *next;
227         EOXactCallback callback;
228         void       *arg;
229 } EOXactCallbackItem;
230
231 static EOXactCallbackItem *EOXact_callbacks = NULL;
232
233 static void (*_RollbackFunc) (void *) = NULL;
234 static void *_RollbackData = NULL;
235
236
237 /* ----------------------------------------------------------------
238  *      transaction state accessors
239  * ----------------------------------------------------------------
240  */
241
242 #ifdef NOT_USED
243
244 /* --------------------------------
245  *      TransactionFlushEnabled()
246  *      SetTransactionFlushEnabled()
247  *
248  *      These are used to test and set the "TransactionFlushState"
249  *      variable.  If this variable is true (the default), then
250  *      the system will flush all dirty buffers to disk at the end
251  *      of each transaction.   If false then we are assuming the
252  *      buffer pool resides in stable main memory, in which case we
253  *      only do writes as necessary.
254  * --------------------------------
255  */
256 static int      TransactionFlushState = 1;
257
258 int
259 TransactionFlushEnabled(void)
260 {
261         return TransactionFlushState;
262 }
263
264 void
265 SetTransactionFlushEnabled(bool state)
266 {
267         TransactionFlushState = (state == true);
268 }
269 #endif
270
271
272 /*
273  *      IsTransactionState
274  *
275  *      This returns true if we are currently running a query
276  *      within an executing transaction.
277  */
278 bool
279 IsTransactionState(void)
280 {
281         TransactionState s = CurrentTransactionState;
282
283         switch (s->state)
284         {
285                 case TRANS_DEFAULT:
286                         return false;
287                 case TRANS_START:
288                         return true;
289                 case TRANS_INPROGRESS:
290                         return true;
291                 case TRANS_COMMIT:
292                         return true;
293                 case TRANS_ABORT:
294                         return true;
295         }
296
297         /*
298          * Shouldn't get here, but lint is not happy with this...
299          */
300         return false;
301 }
302
303 /*
304  *      IsAbortedTransactionBlockState
305  *
306  *      This returns true if we are currently running a query
307  *      within an aborted transaction block.
308  */
309 bool
310 IsAbortedTransactionBlockState(void)
311 {
312         TransactionState s = CurrentTransactionState;
313
314         if (s->blockState == TBLOCK_ABORT)
315                 return true;
316
317         return false;
318 }
319
320
321 /*
322  *      GetCurrentTransactionId
323  */
324 TransactionId
325 GetCurrentTransactionId(void)
326 {
327         TransactionState s = CurrentTransactionState;
328
329         return s->transactionIdData;
330 }
331
332
333 /*
334  *      GetCurrentCommandId
335  */
336 CommandId
337 GetCurrentCommandId(void)
338 {
339         TransactionState s = CurrentTransactionState;
340
341         return s->commandId;
342 }
343
344
345 /*
346  *      GetCurrentTransactionStartTime
347  */
348 AbsoluteTime
349 GetCurrentTransactionStartTime(void)
350 {
351         TransactionState s = CurrentTransactionState;
352
353         return s->startTime;
354 }
355
356
357 /*
358  *      GetCurrentTransactionStartTimeUsec
359  */
360 AbsoluteTime
361 GetCurrentTransactionStartTimeUsec(int *msec)
362 {
363         TransactionState s = CurrentTransactionState;
364
365         *msec = s->startTimeUsec;
366
367         return s->startTime;
368 }
369
370
371 /*
372  *      TransactionIdIsCurrentTransactionId
373  *
374  *      During bootstrap, we cheat and say "it's not my transaction ID" even though
375  *      it is.  Along with transam.c's cheat to say that the bootstrap XID is
376  *      already committed, this causes the tqual.c routines to see previously
377  *      inserted tuples as committed, which is what we need during bootstrap.
378  */
379 bool
380 TransactionIdIsCurrentTransactionId(TransactionId xid)
381 {
382         TransactionState s = CurrentTransactionState;
383
384         if (AMI_OVERRIDE)
385         {
386                 Assert(xid == BootstrapTransactionId);
387                 return false;
388         }
389
390         return TransactionIdEquals(xid, s->transactionIdData);
391 }
392
393
394 /*
395  *      CommandIdIsCurrentCommandId
396  */
397 bool
398 CommandIdIsCurrentCommandId(CommandId cid)
399 {
400         TransactionState s = CurrentTransactionState;
401
402         return (cid == s->commandId) ? true : false;
403 }
404
405
406 /*
407  *      CommandCounterIncrement
408  */
409 void
410 CommandCounterIncrement(void)
411 {
412         TransactionState s = CurrentTransactionState;
413
414         s->commandId += 1;
415         if (s->commandId == FirstCommandId) /* check for overflow */
416                 ereport(ERROR,
417                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
418                                  errmsg("cannot have more than 2^32-1 commands in a transaction")));
419
420         /* Propagate new command ID into query snapshots, if set */
421         if (QuerySnapshot)
422                 QuerySnapshot->curcid = s->commandId;
423         if (SerializableSnapshot)
424                 SerializableSnapshot->curcid = s->commandId;
425
426         /*
427          * make cache changes visible to me.  AtCommit_LocalCache() instead of
428          * AtCommit_Cache() is called here.
429          */
430         AtCommit_LocalCache();
431         AtStart_Cache();
432 }
433
434
435 /* ----------------------------------------------------------------
436  *                                              StartTransaction stuff
437  * ----------------------------------------------------------------
438  */
439
440 /*
441  *      AtStart_Cache
442  */
443 static void
444 AtStart_Cache(void)
445 {
446         AcceptInvalidationMessages();
447 }
448
449 /*
450  *              AtStart_Locks
451  */
452 static void
453 AtStart_Locks(void)
454 {
455         /*
456          * at present, it is unknown to me what belongs here -cim 3/18/90
457          *
458          * There isn't anything to do at the start of a xact for locks. -mer
459          * 5/24/92
460          */
461 }
462
463 /*
464  *      AtStart_Memory
465  */
466 static void
467 AtStart_Memory(void)
468 {
469         /*
470          * We shouldn't have a transaction context already.
471          */
472         Assert(TopTransactionContext == NULL);
473
474         /*
475          * Create a toplevel context for the transaction, and make it active.
476          */
477         TopTransactionContext =
478                 AllocSetContextCreate(TopMemoryContext,
479                                                           "TopTransactionContext",
480                                                           ALLOCSET_DEFAULT_MINSIZE,
481                                                           ALLOCSET_DEFAULT_INITSIZE,
482                                                           ALLOCSET_DEFAULT_MAXSIZE);
483
484         MemoryContextSwitchTo(TopTransactionContext);
485 }
486
487
488 /* ----------------------------------------------------------------
489  *                                              CommitTransaction stuff
490  * ----------------------------------------------------------------
491  */
492
493 /*
494  *      RecordTransactionCommit
495  */
496 void
497 RecordTransactionCommit(void)
498 {
499         /*
500          * If we made neither any XLOG entries nor any temp-rel updates, we
501          * can omit recording the transaction commit at all.
502          */
503         if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate)
504         {
505                 TransactionId xid = GetCurrentTransactionId();
506                 XLogRecPtr      recptr;
507
508                 /* Tell bufmgr and smgr to prepare for commit */
509                 BufmgrCommit();
510
511                 START_CRIT_SECTION();
512
513                 /*
514                  * We only need to log the commit in xlog if the transaction made
515                  * any transaction-controlled XLOG entries.  (Otherwise, its XID
516                  * appears nowhere in permanent storage, so no one else will ever
517                  * care if it committed.)
518                  */
519                 if (MyLastRecPtr.xrecoff != 0)
520                 {
521                         /* Need to emit a commit record */
522                         XLogRecData rdata;
523                         xl_xact_commit xlrec;
524
525                         xlrec.xtime = time(NULL);
526                         rdata.buffer = InvalidBuffer;
527                         rdata.data = (char *) (&xlrec);
528                         rdata.len = SizeOfXactCommit;
529                         rdata.next = NULL;
530
531                         /*
532                          * XXX SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
533                          */
534                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
535                 }
536                 else
537                 {
538                         /* Just flush through last record written by me */
539                         recptr = ProcLastRecEnd;
540                 }
541
542                 /*
543                  * We must flush our XLOG entries to disk if we made any XLOG
544                  * entries, whether in or out of transaction control.  For
545                  * example, if we reported a nextval() result to the client, this
546                  * ensures that any XLOG record generated by nextval will hit the
547                  * disk before we report the transaction committed.
548                  */
549                 if (MyXactMadeXLogEntry)
550                 {
551                         /*
552                          * Sleep before flush! So we can flush more than one commit
553                          * records per single fsync.  (The idea is some other backend
554                          * may do the XLogFlush while we're sleeping.  This needs work
555                          * still, because on most Unixen, the minimum select() delay
556                          * is 10msec or more, which is way too long.)
557                          *
558                          * We do not sleep if enableFsync is not turned on, nor if there
559                          * are fewer than CommitSiblings other backends with active
560                          * transactions.
561                          */
562                         if (CommitDelay > 0 && enableFsync &&
563                                 CountActiveBackends() >= CommitSiblings)
564                         {
565                                 struct timeval delay;
566
567                                 delay.tv_sec = 0;
568                                 delay.tv_usec = CommitDelay;
569                                 (void) select(0, NULL, NULL, NULL, &delay);
570                         }
571
572                         XLogFlush(recptr);
573                 }
574
575                 /*
576                  * We must mark the transaction committed in clog if its XID
577                  * appears either in permanent rels or in local temporary rels. We
578                  * test this by seeing if we made transaction-controlled entries
579                  * *OR* local-rel tuple updates.  Note that if we made only the
580                  * latter, we have not emitted an XLOG record for our commit, and
581                  * so in the event of a crash the clog update might be lost.  This
582                  * is okay because no one else will ever care whether we
583                  * committed.
584                  */
585                 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
586                         TransactionIdCommit(xid);
587
588                 END_CRIT_SECTION();
589         }
590
591         /* Break the chain of back-links in the XLOG records I output */
592         MyLastRecPtr.xrecoff = 0;
593         MyXactMadeXLogEntry = false;
594         MyXactMadeTempRelUpdate = false;
595
596         /* Show myself as out of the transaction in PGPROC array */
597         MyProc->logRec.xrecoff = 0;
598 }
599
600
601 /*
602  *      AtCommit_Cache
603  */
604 static void
605 AtCommit_Cache(void)
606 {
607         /*
608          * Clean up the relation cache.
609          */
610         AtEOXact_RelationCache(true);
611
612         /*
613          * Make catalog changes visible to all backends.
614          */
615         AtEOXactInvalidationMessages(true);
616 }
617
618 /*
619  *      AtCommit_LocalCache
620  */
621 static void
622 AtCommit_LocalCache(void)
623 {
624         /*
625          * Make catalog changes visible to me for the next command.
626          */
627         CommandEndInvalidationMessages(true);
628 }
629
630 /*
631  *      AtCommit_Locks
632  */
633 static void
634 AtCommit_Locks(void)
635 {
636         /*
637          * XXX What if ProcReleaseLocks fails?  (race condition?)
638          *
639          * Then you're up a creek! -mer 5/24/92
640          */
641         ProcReleaseLocks(true);
642 }
643
644 /*
645  *      AtCommit_Memory
646  */
647 static void
648 AtCommit_Memory(void)
649 {
650         /*
651          * Now that we're "out" of a transaction, have the system allocate
652          * things in the top memory context instead of per-transaction
653          * contexts.
654          */
655         MemoryContextSwitchTo(TopMemoryContext);
656
657         /*
658          * Release all transaction-local memory.
659          */
660         Assert(TopTransactionContext != NULL);
661         MemoryContextDelete(TopTransactionContext);
662         TopTransactionContext = NULL;
663 }
664
665 /* ----------------------------------------------------------------
666  *                                              AbortTransaction stuff
667  * ----------------------------------------------------------------
668  */
669
670 /*
671  *      RecordTransactionAbort
672  */
673 static void
674 RecordTransactionAbort(void)
675 {
676         /*
677          * If we made neither any transaction-controlled XLOG entries nor any
678          * temp-rel updates, we can omit recording the transaction abort at
679          * all. No one will ever care that it aborted.
680          */
681         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
682         {
683                 TransactionId xid = GetCurrentTransactionId();
684
685                 /*
686                  * Catch the scenario where we aborted partway through
687                  * RecordTransactionCommit ...
688                  */
689                 if (TransactionIdDidCommit(xid))
690                         elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
691
692                 START_CRIT_SECTION();
693
694                 /*
695                  * We only need to log the abort in XLOG if the transaction made
696                  * any transaction-controlled XLOG entries.  (Otherwise, its XID
697                  * appears nowhere in permanent storage, so no one else will ever
698                  * care if it committed.)  We do not flush XLOG to disk in any
699                  * case, since the default assumption after a crash would be that
700                  * we aborted, anyway.
701                  */
702                 if (MyLastRecPtr.xrecoff != 0)
703                 {
704                         XLogRecData rdata;
705                         xl_xact_abort xlrec;
706                         XLogRecPtr      recptr;
707
708                         xlrec.xtime = time(NULL);
709                         rdata.buffer = InvalidBuffer;
710                         rdata.data = (char *) (&xlrec);
711                         rdata.len = SizeOfXactAbort;
712                         rdata.next = NULL;
713
714                         /*
715                          * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
716                          */
717                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
718                 }
719
720                 /*
721                  * Mark the transaction aborted in clog.  This is not absolutely
722                  * necessary but we may as well do it while we are here.
723                  */
724                 TransactionIdAbort(xid);
725
726                 END_CRIT_SECTION();
727         }
728
729         /* Break the chain of back-links in the XLOG records I output */
730         MyLastRecPtr.xrecoff = 0;
731         MyXactMadeXLogEntry = false;
732         MyXactMadeTempRelUpdate = false;
733
734         /* Show myself as out of the transaction in PGPROC array */
735         MyProc->logRec.xrecoff = 0;
736 }
737
738 /*
739  *      AtAbort_Cache
740  */
741 static void
742 AtAbort_Cache(void)
743 {
744         AtEOXact_RelationCache(false);
745         AtEOXactInvalidationMessages(false);
746 }
747
748 /*
749  *      AtAbort_Locks
750  */
751 static void
752 AtAbort_Locks(void)
753 {
754         /*
755          * XXX What if ProcReleaseLocks() fails?  (race condition?)
756          *
757          * Then you're up a creek without a paddle! -mer
758          */
759         ProcReleaseLocks(false);
760 }
761
762
763 /*
764  *      AtAbort_Memory
765  */
766 static void
767 AtAbort_Memory(void)
768 {
769         /*
770          * Make sure we are in a valid context (not a child of
771          * TopTransactionContext...).  Note that it is possible for this code
772          * to be called when we aren't in a transaction at all; go directly to
773          * TopMemoryContext in that case.
774          */
775         if (TopTransactionContext != NULL)
776         {
777                 MemoryContextSwitchTo(TopTransactionContext);
778
779                 /*
780                  * We do not want to destroy the transaction's global state yet,
781                  * so we can't free any memory here.
782                  */
783         }
784         else
785                 MemoryContextSwitchTo(TopMemoryContext);
786 }
787
788
789 /* ----------------------------------------------------------------
790  *                                              CleanupTransaction stuff
791  * ----------------------------------------------------------------
792  */
793
794 /*
795  *      AtCleanup_Memory
796  */
797 static void
798 AtCleanup_Memory(void)
799 {
800         /*
801          * Now that we're "out" of a transaction, have the system allocate
802          * things in the top memory context instead of per-transaction
803          * contexts.
804          */
805         MemoryContextSwitchTo(TopMemoryContext);
806
807         /*
808          * Release all transaction-local memory.
809          */
810         if (TopTransactionContext != NULL)
811                 MemoryContextDelete(TopTransactionContext);
812         TopTransactionContext = NULL;
813 }
814
815
816 /* ----------------------------------------------------------------
817  *                                              interface routines
818  * ----------------------------------------------------------------
819  */
820
821 /*
822  *      StartTransaction
823  */
824 static void
825 StartTransaction(void)
826 {
827         TransactionState s = CurrentTransactionState;
828
829         /*
830          * check the current transaction state
831          */
832         if (s->state != TRANS_DEFAULT)
833                 elog(WARNING, "StartTransaction and not in default state");
834
835         /*
836          * set the current transaction state information appropriately during
837          * start processing
838          */
839         s->state = TRANS_START;
840
841         /*
842          * Make sure we've freed any old snapshot, and reset xact state variables
843          */
844         FreeXactSnapshot();
845         XactIsoLevel = DefaultXactIsoLevel;
846         XactReadOnly = DefaultXactReadOnly;
847
848         /*
849          * generate a new transaction id
850          */
851         s->transactionIdData = GetNewTransactionId();
852
853         XactLockTableInsert(s->transactionIdData);
854
855         /*
856          * initialize current transaction state fields
857          */
858         s->commandId = FirstCommandId;
859         s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
860
861         /*
862          * initialize the various transaction subsystems
863          */
864         AtStart_Memory();
865         AtStart_Cache();
866         AtStart_Locks();
867
868         /*
869          * Tell the trigger manager to we're starting a transaction
870          */
871         DeferredTriggerBeginXact();
872
873         /*
874          * done with start processing, set current transaction state to "in
875          * progress"
876          */
877         s->state = TRANS_INPROGRESS;
878
879 }
880
881 /*
882  *      CommitTransaction
883  */
884 static void
885 CommitTransaction(void)
886 {
887         TransactionState s = CurrentTransactionState;
888
889         /*
890          * check the current transaction state
891          */
892         if (s->state != TRANS_INPROGRESS)
893                 elog(WARNING, "CommitTransaction and not in in-progress state");
894
895         /*
896          * Tell the trigger manager that this transaction is about to be
897          * committed. He'll invoke all trigger deferred until XACT before we
898          * really start on committing the transaction.
899          */
900         DeferredTriggerEndXact();
901
902         /*
903          * Similarly, let ON COMMIT management do its thing before we start to
904          * commit.
905          */
906         PreCommit_on_commit_actions();
907
908         /* Prevent cancel/die interrupt while cleaning up */
909         HOLD_INTERRUPTS();
910
911         /*
912          * set the current transaction state information appropriately during
913          * the abort processing
914          */
915         s->state = TRANS_COMMIT;
916
917         /*
918          * Do pre-commit processing (most of this stuff requires database
919          * access, and in fact could still cause an error...)
920          */
921
922         AtCommit_Portals();
923
924         /* handle commit for large objects [ PA, 7/17/98 ] */
925         /* XXX probably this does not belong here */
926         lo_commit(true);
927
928         /* NOTIFY commit must come before lower-level cleanup */
929         AtCommit_Notify();
930
931         /* Update the flat password file if we changed pg_shadow or pg_group */
932         AtEOXact_UpdatePasswordFile(true);
933
934         /*
935          * Here is where we really truly commit.
936          */
937         RecordTransactionCommit();
938
939         /*
940          * Let others know about no transaction in progress by me. Note that
941          * this must be done _before_ releasing locks we hold and _after_
942          * RecordTransactionCommit.
943          *
944          * LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by
945          * xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if
946          * xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0
947          * as running as well or it will see two tuple versions - one deleted
948          * by xid 1 and one inserted by xid 0.  See notes in GetSnapshotData.
949          */
950         if (MyProc != (PGPROC *) NULL)
951         {
952                 /* Lock SInvalLock because that's what GetSnapshotData uses. */
953                 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
954                 MyProc->xid = InvalidTransactionId;
955                 MyProc->xmin = InvalidTransactionId;
956                 LWLockRelease(SInvalLock);
957         }
958
959         /*
960          * This is all post-commit cleanup.  Note that if an error is raised
961          * here, it's too late to abort the transaction.  This should be just
962          * noncritical resource releasing.
963          *
964          * The ordering of operations is not entirely random.  The idea is:
965          * release resources visible to other backends (eg, files, buffer
966          * pins); then release locks; then release backend-local resources. We
967          * want to release locks at the point where any backend waiting for us
968          * will see our transaction as being fully cleaned up.
969          */
970
971         smgrDoPendingDeletes(true);
972         AtCommit_Cache();
973         AtEOXact_Buffers(true);
974         /* smgrcommit already done */
975
976         AtCommit_Locks();
977
978         CallEOXactCallbacks(true);
979         AtEOXact_GUC(true);
980         AtEOXact_SPI();
981         AtEOXact_gist();
982         AtEOXact_hash();
983         AtEOXact_nbtree();
984         AtEOXact_rtree();
985         AtEOXact_on_commit_actions(true);
986         AtEOXact_Namespace(true);
987         AtEOXact_CatCache(true);
988         AtEOXact_Files();
989         pgstat_count_xact_commit();
990         AtCommit_Memory();
991
992         /*
993          * done with commit processing, set current transaction state back to
994          * default
995          */
996         s->state = TRANS_DEFAULT;
997
998         RESUME_INTERRUPTS();
999 }
1000
1001 /*
1002  *      AbortTransaction
1003  */
1004 static void
1005 AbortTransaction(void)
1006 {
1007         TransactionState s = CurrentTransactionState;
1008
1009         /* Prevent cancel/die interrupt while cleaning up */
1010         HOLD_INTERRUPTS();
1011
1012         /*
1013          * Release any LW locks we might be holding as quickly as possible.
1014          * (Regular locks, however, must be held till we finish aborting.)
1015          * Releasing LW locks is critical since we might try to grab them
1016          * again while cleaning up!
1017          */
1018         LWLockReleaseAll();
1019
1020         /* Clean up buffer I/O and buffer context locks, too */
1021         AbortBufferIO();
1022         UnlockBuffers();
1023
1024         /*
1025          * Also clean up any open wait for lock, since the lock manager will
1026          * choke if we try to wait for another lock before doing this.
1027          */
1028         LockWaitCancel();
1029
1030         /*
1031          * check the current transaction state
1032          */
1033         if (s->state != TRANS_INPROGRESS)
1034                 elog(WARNING, "AbortTransaction and not in in-progress state");
1035
1036         /*
1037          * set the current transaction state information appropriately during
1038          * the abort processing
1039          */
1040         s->state = TRANS_ABORT;
1041
1042         /* Make sure we are in a valid memory context */
1043         AtAbort_Memory();
1044
1045         /*
1046          * Reset user id which might have been changed transiently
1047          */
1048         SetUserId(GetSessionUserId());
1049
1050         /*
1051          * do abort processing
1052          */
1053         DeferredTriggerAbortXact();
1054         AtAbort_Portals();
1055         lo_commit(false);                       /* 'false' means it's abort */
1056         AtAbort_Notify();
1057         AtEOXact_UpdatePasswordFile(false);
1058
1059         /* Advertise the fact that we aborted in pg_clog. */
1060         RecordTransactionAbort();
1061
1062         /*
1063          * Let others know about no transaction in progress by me. Note that
1064          * this must be done _before_ releasing locks we hold and _after_
1065          * RecordTransactionAbort.
1066          */
1067         if (MyProc != (PGPROC *) NULL)
1068         {
1069                 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1070                 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1071                 MyProc->xid = InvalidTransactionId;
1072                 MyProc->xmin = InvalidTransactionId;
1073                 LWLockRelease(SInvalLock);
1074         }
1075
1076         /*
1077          * Post-abort cleanup.  See notes in CommitTransaction() concerning
1078          * ordering.
1079          */
1080
1081         smgrDoPendingDeletes(false);
1082         AtAbort_Cache();
1083         AtEOXact_Buffers(false);
1084         smgrabort();
1085
1086         AtAbort_Locks();
1087
1088         CallEOXactCallbacks(false);
1089         AtEOXact_GUC(false);
1090         AtEOXact_SPI();
1091         AtEOXact_gist();
1092         AtEOXact_hash();
1093         AtEOXact_nbtree();
1094         AtEOXact_rtree();
1095         AtEOXact_on_commit_actions(false);
1096         AtEOXact_Namespace(false);
1097         AtEOXact_CatCache(false);
1098         AtEOXact_Files();
1099         SetReindexProcessing(InvalidOid, InvalidOid);
1100         pgstat_count_xact_rollback();
1101
1102         /*
1103          * State remains TRANS_ABORT until CleanupTransaction().
1104          */
1105         RESUME_INTERRUPTS();
1106 }
1107
1108 /*
1109  *      CleanupTransaction
1110  */
1111 static void
1112 CleanupTransaction(void)
1113 {
1114         TransactionState s = CurrentTransactionState;
1115
1116         /*
1117          * State should still be TRANS_ABORT from AbortTransaction().
1118          */
1119         if (s->state != TRANS_ABORT)
1120                 elog(FATAL, "CleanupTransaction and not in abort state");
1121
1122         /*
1123          * do abort cleanup processing
1124          */
1125         AtCleanup_Portals();            /* now safe to release portal memory */
1126         AtCleanup_Memory();                     /* and transaction memory */
1127
1128         /*
1129          * done with abort processing, set current transaction state back to
1130          * default
1131          */
1132         s->state = TRANS_DEFAULT;
1133 }
1134
1135 /*
1136  *      StartTransactionCommand
1137  */
1138 void
1139 StartTransactionCommand(void)
1140 {
1141         TransactionState s = CurrentTransactionState;
1142
1143         switch (s->blockState)
1144         {
1145                         /*
1146                          * if we aren't in a transaction block, we just do our usual
1147                          * start transaction.
1148                          */
1149                 case TBLOCK_DEFAULT:
1150                         StartTransaction();
1151                         break;
1152
1153                         /*
1154                          * We should never experience this -- if we do it means the
1155                          * BEGIN state was not changed in the previous
1156                          * CommitTransactionCommand().  If we get it, we print a
1157                          * warning and change to the in-progress state.
1158                          */
1159                 case TBLOCK_BEGIN:
1160                         elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_BEGIN");
1161                         s->blockState = TBLOCK_INPROGRESS;
1162                         break;
1163
1164                         /*
1165                          * This is the case when are somewhere in a transaction block
1166                          * and about to start a new command.  For now we do nothing
1167                          * but someday we may do command-local resource
1168                          * initialization.
1169                          */
1170                 case TBLOCK_INPROGRESS:
1171                         break;
1172
1173                         /*
1174                          * As with BEGIN, we should never experience this if we do it
1175                          * means the END state was not changed in the previous
1176                          * CommitTransactionCommand().  If we get it, we print a
1177                          * warning, commit the transaction, start a new transaction
1178                          * and change to the default state.
1179                          */
1180                 case TBLOCK_END:
1181                         elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_END");
1182                         s->blockState = TBLOCK_DEFAULT;
1183                         CommitTransaction();
1184                         StartTransaction();
1185                         break;
1186
1187                         /*
1188                          * Here we are in the middle of a transaction block but one of
1189                          * the commands caused an abort so we do nothing but remain in
1190                          * the abort state.  Eventually we will get to the "END
1191                          * TRANSACTION" which will set things straight.
1192                          */
1193                 case TBLOCK_ABORT:
1194                         break;
1195
1196                         /*
1197                          * This means we somehow aborted and the last call to
1198                          * CommitTransactionCommand() didn't clear the state so we
1199                          * remain in the ENDABORT state and maybe next time we get to
1200                          * CommitTransactionCommand() the state will get reset to
1201                          * default.
1202                          */
1203                 case TBLOCK_ENDABORT:
1204                         elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_ENDABORT");
1205                         break;
1206         }
1207
1208         /*
1209          * We must switch to TopTransactionContext before returning. This is
1210          * already done if we called StartTransaction, otherwise not.
1211          */
1212         Assert(TopTransactionContext != NULL);
1213         MemoryContextSwitchTo(TopTransactionContext);
1214 }
1215
1216 /*
1217  *      CommitTransactionCommand
1218  */
1219 void
1220 CommitTransactionCommand(void)
1221 {
1222         TransactionState s = CurrentTransactionState;
1223
1224         switch (s->blockState)
1225         {
1226                         /*
1227                          * If we aren't in a transaction block, just do our usual
1228                          * transaction commit.
1229                          */
1230                 case TBLOCK_DEFAULT:
1231                         CommitTransaction();
1232                         break;
1233
1234                         /*
1235                          * This is the case right after we get a "BEGIN TRANSACTION"
1236                          * command, but the user hasn't done anything else yet, so we
1237                          * change to the "transaction block in progress" state and
1238                          * return.
1239                          */
1240                 case TBLOCK_BEGIN:
1241                         s->blockState = TBLOCK_INPROGRESS;
1242                         break;
1243
1244                         /*
1245                          * This is the case when we have finished executing a command
1246                          * someplace within a transaction block.  We increment the
1247                          * command counter and return.
1248                          */
1249                 case TBLOCK_INPROGRESS:
1250                         CommandCounterIncrement();
1251                         break;
1252
1253                         /*
1254                          * This is the case when we just got the "END TRANSACTION"
1255                          * statement, so we commit the transaction and go back to the
1256                          * default state.
1257                          */
1258                 case TBLOCK_END:
1259                         CommitTransaction();
1260                         s->blockState = TBLOCK_DEFAULT;
1261                         break;
1262
1263                         /*
1264                          * Here we are in the middle of a transaction block but one of
1265                          * the commands caused an abort so we do nothing but remain in
1266                          * the abort state.  Eventually we will get to the "END
1267                          * TRANSACTION" which will set things straight.
1268                          */
1269                 case TBLOCK_ABORT:
1270                         break;
1271
1272                         /*
1273                          * Here we were in an aborted transaction block which just
1274                          * processed the "END TRANSACTION" command from the user, so
1275                          * clean up and return to the default state.
1276                          */
1277                 case TBLOCK_ENDABORT:
1278                         CleanupTransaction();
1279                         s->blockState = TBLOCK_DEFAULT;
1280                         break;
1281         }
1282 }
1283
1284 /*
1285  *      AbortCurrentTransaction
1286  */
1287 void
1288 AbortCurrentTransaction(void)
1289 {
1290         TransactionState s = CurrentTransactionState;
1291
1292         switch (s->blockState)
1293         {
1294                         /*
1295                          * if we aren't in a transaction block, we just do the basic
1296                          * abort & cleanup transaction.
1297                          */
1298                 case TBLOCK_DEFAULT:
1299                         AbortTransaction();
1300                         CleanupTransaction();
1301                         break;
1302
1303                         /*
1304                          * If we are in the TBLOCK_BEGIN it means something screwed up
1305                          * right after reading "BEGIN TRANSACTION" so we enter the
1306                          * abort state.  Eventually an "END TRANSACTION" will fix
1307                          * things.
1308                          */
1309                 case TBLOCK_BEGIN:
1310                         s->blockState = TBLOCK_ABORT;
1311                         AbortTransaction();
1312                         /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1313                         break;
1314
1315                         /*
1316                          * This is the case when are somewhere in a transaction block
1317                          * which aborted so we abort the transaction and set the ABORT
1318                          * state.  Eventually an "END TRANSACTION" will fix things and
1319                          * restore us to a normal state.
1320                          */
1321                 case TBLOCK_INPROGRESS:
1322                         s->blockState = TBLOCK_ABORT;
1323                         AbortTransaction();
1324                         /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1325                         break;
1326
1327                         /*
1328                          * Here, the system was fouled up just after the user wanted
1329                          * to end the transaction block so we abort the transaction
1330                          * and put us back into the default state.
1331                          */
1332                 case TBLOCK_END:
1333                         s->blockState = TBLOCK_DEFAULT;
1334                         AbortTransaction();
1335                         CleanupTransaction();
1336                         break;
1337
1338                         /*
1339                          * Here, we are already in an aborted transaction state and
1340                          * are waiting for an "END TRANSACTION" to come along and lo
1341                          * and behold, we abort again! So we just remain in the abort
1342                          * state.
1343                          */
1344                 case TBLOCK_ABORT:
1345                         break;
1346
1347                         /*
1348                          * Here we were in an aborted transaction block which just
1349                          * processed the "END TRANSACTION" command but somehow aborted
1350                          * again.. since we must have done the abort processing, we
1351                          * clean up and return to the default state.
1352                          */
1353                 case TBLOCK_ENDABORT:
1354                         CleanupTransaction();
1355                         s->blockState = TBLOCK_DEFAULT;
1356                         break;
1357         }
1358 }
1359
1360 /*
1361  *      PreventTransactionChain
1362  *
1363  *      This routine is to be called by statements that must not run inside
1364  *      a transaction block, typically because they have non-rollback-able
1365  *      side effects or do internal commits.
1366  *
1367  *      If we have already started a transaction block, issue an error; also issue
1368  *      an error if we appear to be running inside a user-defined function (which
1369  *      could issue more commands and possibly cause a failure after the statement
1370  *      completes).
1371  *
1372  *      stmtNode: pointer to parameter block for statement; this is used in
1373  *      a very klugy way to determine whether we are inside a function.
1374  *      stmtType: statement type name for error messages.
1375  */
1376 void
1377 PreventTransactionChain(void *stmtNode, const char *stmtType)
1378 {
1379         /*
1380          * xact block already started?
1381          */
1382         if (IsTransactionBlock())
1383                 ereport(ERROR,
1384                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1385                 /* translator: %s represents an SQL statement name */
1386                                  errmsg("%s cannot run inside a transaction block",
1387                                                 stmtType)));
1388
1389         /*
1390          * Are we inside a function call?  If the statement's parameter block
1391          * was allocated in QueryContext, assume it is an interactive command.
1392          * Otherwise assume it is coming from a function.
1393          */
1394         if (!MemoryContextContains(QueryContext, stmtNode))
1395                 ereport(ERROR,
1396                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1397                 /* translator: %s represents an SQL statement name */
1398                          errmsg("%s cannot be executed from a function", stmtType)));
1399         /* If we got past IsTransactionBlock test, should be in default state */
1400         if (CurrentTransactionState->blockState != TBLOCK_DEFAULT)
1401                 elog(ERROR, "cannot prevent transaction chain");
1402         /* all okay */
1403 }
1404
1405 /*
1406  *      RequireTransactionChain
1407  *
1408  *      This routine is to be called by statements that must run inside
1409  *      a transaction block, because they have no effects that persist past
1410  *      transaction end (and so calling them outside a transaction block
1411  *      is presumably an error).  DECLARE CURSOR is an example.
1412  *
1413  *      If we appear to be running inside a user-defined function, we do not
1414  *      issue an error, since the function could issue more commands that make
1415  *      use of the current statement's results.  Thus this is an inverse for
1416  *      PreventTransactionChain.
1417  *
1418  *      stmtNode: pointer to parameter block for statement; this is used in
1419  *      a very klugy way to determine whether we are inside a function.
1420  *      stmtType: statement type name for error messages.
1421  */
1422 void
1423 RequireTransactionChain(void *stmtNode, const char *stmtType)
1424 {
1425         /*
1426          * xact block already started?
1427          */
1428         if (IsTransactionBlock())
1429                 return;
1430
1431         /*
1432          * Are we inside a function call?  If the statement's parameter block
1433          * was allocated in QueryContext, assume it is an interactive command.
1434          * Otherwise assume it is coming from a function.
1435          */
1436         if (!MemoryContextContains(QueryContext, stmtNode))
1437                 return;
1438         ereport(ERROR,
1439                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1440         /* translator: %s represents an SQL statement name */
1441                          errmsg("%s may only be used in transaction blocks",
1442                                         stmtType)));
1443 }
1444
1445
1446 /*
1447  * Register or deregister callback functions for end-of-xact cleanup
1448  *
1449  * These functions are intended for use by dynamically loaded modules.
1450  * For built-in modules we generally just hardwire the appropriate calls
1451  * (mainly because it's easier to control the order that way, where needed).
1452  *
1453  * Note that the callback occurs post-commit or post-abort, so the callback
1454  * functions can only do noncritical cleanup.
1455  */
1456 void
1457 RegisterEOXactCallback(EOXactCallback callback, void *arg)
1458 {
1459         EOXactCallbackItem *item;
1460
1461         item = (EOXactCallbackItem *)
1462                 MemoryContextAlloc(TopMemoryContext, sizeof(EOXactCallbackItem));
1463         item->callback = callback;
1464         item->arg = arg;
1465         item->next = EOXact_callbacks;
1466         EOXact_callbacks = item;
1467 }
1468
1469 void
1470 UnregisterEOXactCallback(EOXactCallback callback, void *arg)
1471 {
1472         EOXactCallbackItem *item;
1473         EOXactCallbackItem *prev;
1474
1475         prev = NULL;
1476         for (item = EOXact_callbacks; item; prev = item, item = item->next)
1477         {
1478                 if (item->callback == callback && item->arg == arg)
1479                 {
1480                         if (prev)
1481                                 prev->next = item->next;
1482                         else
1483                                 EOXact_callbacks = item->next;
1484                         pfree(item);
1485                         break;
1486                 }
1487         }
1488 }
1489
1490 static void
1491 CallEOXactCallbacks(bool isCommit)
1492 {
1493         EOXactCallbackItem *item;
1494
1495         for (item = EOXact_callbacks; item; item = item->next)
1496         {
1497                 (*item->callback) (isCommit, item->arg);
1498         }
1499 }
1500
1501
1502 /* ----------------------------------------------------------------
1503  *                                         transaction block support
1504  * ----------------------------------------------------------------
1505  */
1506 /*
1507  *      BeginTransactionBlock
1508  */
1509 void
1510 BeginTransactionBlock(void)
1511 {
1512         TransactionState s = CurrentTransactionState;
1513
1514         /*
1515          * check the current transaction state
1516          */
1517         if (s->blockState != TBLOCK_DEFAULT)
1518                 ereport(WARNING,
1519                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1520                                  errmsg("there is already a transaction in progress")));
1521
1522         /*
1523          * set the current transaction block state information appropriately
1524          * during begin processing
1525          */
1526         s->blockState = TBLOCK_BEGIN;
1527
1528         /*
1529          * do begin processing here.  Nothing to do at present.
1530          */
1531
1532         /*
1533          * done with begin processing, set block state to inprogress
1534          */
1535         s->blockState = TBLOCK_INPROGRESS;
1536 }
1537
1538 /*
1539  *      EndTransactionBlock
1540  */
1541 void
1542 EndTransactionBlock(void)
1543 {
1544         TransactionState s = CurrentTransactionState;
1545
1546         /*
1547          * check the current transaction state
1548          */
1549         if (s->blockState == TBLOCK_INPROGRESS)
1550         {
1551                 /*
1552                  * here we are in a transaction block which should commit when we
1553                  * get to the upcoming CommitTransactionCommand() so we set the
1554                  * state to "END".      CommitTransactionCommand() will recognize this
1555                  * and commit the transaction and return us to the default state
1556                  */
1557                 s->blockState = TBLOCK_END;
1558                 return;
1559         }
1560
1561         if (s->blockState == TBLOCK_ABORT)
1562         {
1563                 /*
1564                  * here, we are in a transaction block which aborted and since the
1565                  * AbortTransaction() was already done, we do whatever is needed
1566                  * and change to the special "END ABORT" state.  The upcoming
1567                  * CommitTransactionCommand() will recognise this and then put us
1568                  * back in the default state.
1569                  */
1570                 s->blockState = TBLOCK_ENDABORT;
1571                 return;
1572         }
1573
1574         /*
1575          * here, the user issued COMMIT when not inside a transaction. Issue a
1576          * WARNING and go to abort state.  The upcoming call to
1577          * CommitTransactionCommand() will then put us back into the default
1578          * state.
1579          */
1580         ereport(WARNING,
1581                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1582                          errmsg("there is no transaction in progress")));
1583         AbortTransaction();
1584         s->blockState = TBLOCK_ENDABORT;
1585 }
1586
1587 /*
1588  *      AbortTransactionBlock
1589  */
1590 #ifdef NOT_USED
1591 static void
1592 AbortTransactionBlock(void)
1593 {
1594         TransactionState s = CurrentTransactionState;
1595
1596         /*
1597          * check the current transaction state
1598          */
1599         if (s->blockState == TBLOCK_INPROGRESS)
1600         {
1601                 /*
1602                  * here we were inside a transaction block something screwed up
1603                  * inside the system so we enter the abort state, do the abort
1604                  * processing and then return. We remain in the abort state until
1605                  * we see an END TRANSACTION command.
1606                  */
1607                 s->blockState = TBLOCK_ABORT;
1608                 AbortTransaction();
1609                 return;
1610         }
1611
1612         /*
1613          * here, the user issued ABORT when not inside a transaction. Issue a
1614          * WARNING and go to abort state.  The upcoming call to
1615          * CommitTransactionCommand() will then put us back into the default
1616          * state.
1617          */
1618         ereport(WARNING,
1619                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1620                          errmsg("there is no transaction in progress")));
1621         AbortTransaction();
1622         s->blockState = TBLOCK_ENDABORT;
1623 }
1624 #endif
1625
1626 /*
1627  *      UserAbortTransactionBlock
1628  */
1629 void
1630 UserAbortTransactionBlock(void)
1631 {
1632         TransactionState s = CurrentTransactionState;
1633
1634         /*
1635          * if the transaction has already been automatically aborted with an
1636          * error, and the user subsequently types 'abort', allow it.  (the
1637          * behavior is the same as if they had typed 'end'.)
1638          */
1639         if (s->blockState == TBLOCK_ABORT)
1640         {
1641                 s->blockState = TBLOCK_ENDABORT;
1642                 return;
1643         }
1644
1645         if (s->blockState == TBLOCK_INPROGRESS)
1646         {
1647                 /*
1648                  * here we were inside a transaction block and we got an abort
1649                  * command from the user, so we move to the abort state, do the
1650                  * abort processing and then change to the ENDABORT state so we
1651                  * will end up in the default state after the upcoming
1652                  * CommitTransactionCommand().
1653                  */
1654                 s->blockState = TBLOCK_ABORT;
1655                 AbortTransaction();
1656                 s->blockState = TBLOCK_ENDABORT;
1657                 return;
1658         }
1659
1660         /*
1661          * here, the user issued ABORT when not inside a transaction. Issue a
1662          * WARNING and go to abort state.  The upcoming call to
1663          * CommitTransactionCommand() will then put us back into the default
1664          * state.
1665          */
1666         ereport(WARNING,
1667                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1668                          errmsg("there is no transaction in progress")));
1669         AbortTransaction();
1670         s->blockState = TBLOCK_ENDABORT;
1671 }
1672
1673 /*
1674  *      AbortOutOfAnyTransaction
1675  *
1676  *      This routine is provided for error recovery purposes.  It aborts any
1677  *      active transaction or transaction block, leaving the system in a known
1678  *      idle state.
1679  */
1680 void
1681 AbortOutOfAnyTransaction(void)
1682 {
1683         TransactionState s = CurrentTransactionState;
1684
1685         /*
1686          * Get out of any low-level transaction
1687          */
1688         switch (s->state)
1689         {
1690                 case TRANS_START:
1691                 case TRANS_INPROGRESS:
1692                 case TRANS_COMMIT:
1693                         /* In a transaction, so clean up */
1694                         AbortTransaction();
1695                         CleanupTransaction();
1696                         break;
1697                 case TRANS_ABORT:
1698                         /* AbortTransaction already done, still need Cleanup */
1699                         CleanupTransaction();
1700                         break;
1701                 case TRANS_DEFAULT:
1702                         /* Not in a transaction, do nothing */
1703                         break;
1704         }
1705
1706         /*
1707          * Now reset the high-level state
1708          */
1709         s->blockState = TBLOCK_DEFAULT;
1710 }
1711
1712 /*
1713  * IsTransactionBlock --- are we within a transaction block?
1714  */
1715 bool
1716 IsTransactionBlock(void)
1717 {
1718         TransactionState s = CurrentTransactionState;
1719
1720         if (s->blockState == TBLOCK_DEFAULT)
1721                 return false;
1722
1723         return true;
1724 }
1725
1726 /*
1727  * IsTransactionOrTransactionBlock --- are we within either a transaction
1728  * or a transaction block?  (The backend is only really "idle" when this
1729  * returns false.)
1730  *
1731  * This should match up with IsTransactionBlock and IsTransactionState.
1732  */
1733 bool
1734 IsTransactionOrTransactionBlock(void)
1735 {
1736         TransactionState s = CurrentTransactionState;
1737
1738         if (s->blockState == TBLOCK_DEFAULT && s->state == TRANS_DEFAULT)
1739                 return false;
1740
1741         return true;
1742 }
1743
1744 /*
1745  * TransactionBlockStatusCode - return status code to send in ReadyForQuery
1746  */
1747 char
1748 TransactionBlockStatusCode(void)
1749 {
1750         TransactionState s = CurrentTransactionState;
1751
1752         switch (s->blockState)
1753         {
1754                 case TBLOCK_DEFAULT:
1755                         return 'I';                     /* idle --- not in transaction */
1756                 case TBLOCK_BEGIN:
1757                 case TBLOCK_INPROGRESS:
1758                 case TBLOCK_END:
1759                         return 'T';                     /* in transaction */
1760                 case TBLOCK_ABORT:
1761                 case TBLOCK_ENDABORT:
1762                         return 'E';                     /* in failed transaction */
1763         }
1764
1765         /* should never get here */
1766         elog(ERROR, "invalid transaction block state: %d",
1767                  (int) s->blockState);
1768         return 0;                                       /* keep compiler quiet */
1769 }
1770
1771
1772 /*
1773  *      XLOG support routines
1774  */
1775
1776 void
1777 xact_redo(XLogRecPtr lsn, XLogRecord *record)
1778 {
1779         uint8           info = record->xl_info & ~XLR_INFO_MASK;
1780
1781         if (info == XLOG_XACT_COMMIT)
1782         {
1783                 TransactionIdCommit(record->xl_xid);
1784                 /* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */
1785         }
1786         else if (info == XLOG_XACT_ABORT)
1787         {
1788                 TransactionIdAbort(record->xl_xid);
1789                 /* SHOULD REMOVE FILES OF ALL FAILED-TO-BE-CREATED RELATIONS */
1790         }
1791         else
1792                 elog(PANIC, "xact_redo: unknown op code %u", info);
1793 }
1794
1795 void
1796 xact_undo(XLogRecPtr lsn, XLogRecord *record)
1797 {
1798         uint8           info = record->xl_info & ~XLR_INFO_MASK;
1799
1800         if (info == XLOG_XACT_COMMIT)           /* shouldn't be called by XLOG */
1801                 elog(PANIC, "xact_undo: can't undo committed xaction");
1802         else if (info != XLOG_XACT_ABORT)
1803                 elog(PANIC, "xact_redo: unknown op code %u", info);
1804 }
1805
1806 void
1807 xact_desc(char *buf, uint8 xl_info, char *rec)
1808 {
1809         uint8           info = xl_info & ~XLR_INFO_MASK;
1810
1811         if (info == XLOG_XACT_COMMIT)
1812         {
1813                 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
1814                 struct tm  *tm = localtime(&xlrec->xtime);
1815
1816                 sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
1817                                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1818                                 tm->tm_hour, tm->tm_min, tm->tm_sec);
1819         }
1820         else if (info == XLOG_XACT_ABORT)
1821         {
1822                 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
1823                 struct tm  *tm = localtime(&xlrec->xtime);
1824
1825                 sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
1826                                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1827                                 tm->tm_hour, tm->tm_min, tm->tm_sec);
1828         }
1829         else
1830                 strcat(buf, "UNKNOWN");
1831 }
1832
1833 void
1834                         XactPushRollback(void (*func) (void *), void *data)
1835 {
1836 #ifdef XLOG_II
1837         if (_RollbackFunc != NULL)
1838                 elog(PANIC, "XactPushRollback: already installed");
1839 #endif
1840
1841         _RollbackFunc = func;
1842         _RollbackData = data;
1843 }
1844
1845 void
1846 XactPopRollback(void)
1847 {
1848         _RollbackFunc = NULL;
1849 }