xact.c

来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 2,442 行 · 第 1/5 页

C
2,442
字号
	TransactionState s = CurrentTransactionState;	/*	 * State should still be TRANS_ABORT from AbortTransaction().	 */	if (s->state != TRANS_ABORT)		elog(FATAL, "CleanupTransaction: unexpected state %s",			 TransStateAsString(s->state));	/*	 * do abort cleanup processing	 */	AtCleanup_Portals();		/* now safe to release portal memory */	CurrentResourceOwner = NULL;	/* and resource owner */	if (TopTransactionResourceOwner)		ResourceOwnerDelete(TopTransactionResourceOwner);	s->curTransactionOwner = NULL;	CurTransactionResourceOwner = NULL;	TopTransactionResourceOwner = NULL;	AtCleanup_Memory();			/* and transaction memory */	s->transactionId = InvalidTransactionId;	s->subTransactionId = InvalidSubTransactionId;	s->nestingLevel = 0;	s->childXids = NIL;	/*	 * done with abort processing, set current transaction state back to	 * default	 */	s->state = TRANS_DEFAULT;}/* *	StartTransactionCommand */voidStartTransactionCommand(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{			/*			 * if we aren't in a transaction block, we just do our usual start			 * transaction.			 */		case TBLOCK_DEFAULT:			StartTransaction();			s->blockState = TBLOCK_STARTED;			break;			/*			 * We are somewhere in a transaction block or subtransaction and			 * about to start a new command.  For now we do nothing, but			 * someday we may do command-local resource initialization. (Note			 * that any needed CommandCounterIncrement was done by the			 * previous CommitTransactionCommand.)			 */		case TBLOCK_INPROGRESS:		case TBLOCK_SUBINPROGRESS:			break;			/*			 * Here we are in a failed transaction block (one of the commands			 * caused an abort) so we do nothing but remain in the abort			 * state.  Eventually we will get a ROLLBACK command which will			 * get us out of this state.  (It is up to other code to ensure			 * that no commands other than ROLLBACK will be processed in these			 * states.)			 */		case TBLOCK_ABORT:		case TBLOCK_SUBABORT:			break;			/* These cases are invalid. */		case TBLOCK_STARTED:		case TBLOCK_BEGIN:		case TBLOCK_SUBBEGIN:		case TBLOCK_END:		case TBLOCK_SUBEND:		case TBLOCK_ABORT_END:		case TBLOCK_SUBABORT_END:		case TBLOCK_ABORT_PENDING:		case TBLOCK_SUBABORT_PENDING:		case TBLOCK_SUBRESTART:		case TBLOCK_SUBABORT_RESTART:		case TBLOCK_PREPARE:			elog(ERROR, "StartTransactionCommand: unexpected state %s",				 BlockStateAsString(s->blockState));			break;	}	/*	 * We must switch to CurTransactionContext before returning. This is	 * already done if we called StartTransaction, otherwise not.	 */	Assert(CurTransactionContext != NULL);	MemoryContextSwitchTo(CurTransactionContext);}/* *	CommitTransactionCommand */voidCommitTransactionCommand(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{			/*			 * This shouldn't happen, because it means the previous			 * StartTransactionCommand didn't set the STARTED state			 * appropriately.			 */		case TBLOCK_DEFAULT:			elog(FATAL, "CommitTransactionCommand: unexpected state %s",				 BlockStateAsString(s->blockState));			break;			/*			 * If we aren't in a transaction block, just do our usual			 * transaction commit, and return to the idle state.			 */		case TBLOCK_STARTED:			CommitTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * We are completing a "BEGIN TRANSACTION" command, so we change			 * to the "transaction block in progress" state and return.  (We			 * assume the BEGIN did nothing to the database, so we need no			 * CommandCounterIncrement.)			 */		case TBLOCK_BEGIN:			s->blockState = TBLOCK_INPROGRESS;			break;			/*			 * This is the case when we have finished executing a command			 * someplace within a transaction block.  We increment the command			 * counter and return.			 */		case TBLOCK_INPROGRESS:		case TBLOCK_SUBINPROGRESS:			CommandCounterIncrement();			break;			/*			 * We are completing a "COMMIT" command.  Do it and return to the			 * idle state.			 */		case TBLOCK_END:			CommitTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * Here we are in the middle of a transaction block but one of the			 * commands caused an abort so we do nothing but remain in the			 * abort state.  Eventually we will get a ROLLBACK comand.			 */		case TBLOCK_ABORT:		case TBLOCK_SUBABORT:			break;			/*			 * Here we were in an aborted transaction block and we just got			 * the ROLLBACK command from the user, so clean up the			 * already-aborted transaction and return to the idle state.			 */		case TBLOCK_ABORT_END:			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * Here we were in a perfectly good transaction block but the user			 * told us to ROLLBACK anyway.	We have to abort the transaction			 * and then clean up.			 */		case TBLOCK_ABORT_PENDING:			AbortTransaction();			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * We are completing a "PREPARE TRANSACTION" command.  Do it and			 * return to the idle state.			 */		case TBLOCK_PREPARE:			PrepareTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * We were just issued a SAVEPOINT inside a transaction block.			 * Start a subtransaction.	(DefineSavepoint already did			 * PushTransaction, so as to have someplace to put the SUBBEGIN			 * state.)			 */		case TBLOCK_SUBBEGIN:			StartSubTransaction();			s->blockState = TBLOCK_SUBINPROGRESS;			break;			/*			 * We were issued a COMMIT or RELEASE command, so we end the			 * current subtransaction and return to the parent transaction.			 * The parent might be ended too, so repeat till we are all the			 * way out or find an INPROGRESS transaction.			 */		case TBLOCK_SUBEND:			do			{				CommitSubTransaction();				s = CurrentTransactionState;	/* changed by pop */			} while (s->blockState == TBLOCK_SUBEND);			/* If we had a COMMIT command, finish off the main xact too */			if (s->blockState == TBLOCK_END)			{				Assert(s->parent == NULL);				CommitTransaction();				s->blockState = TBLOCK_DEFAULT;			}			else if (s->blockState == TBLOCK_PREPARE)			{				Assert(s->parent == NULL);				PrepareTransaction();				s->blockState = TBLOCK_DEFAULT;			}			else			{				Assert(s->blockState == TBLOCK_INPROGRESS ||					   s->blockState == TBLOCK_SUBINPROGRESS);			}			break;			/*			 * The current already-failed subtransaction is ending due to a			 * ROLLBACK or ROLLBACK TO command, so pop it and recursively			 * examine the parent (which could be in any of several states).			 */		case TBLOCK_SUBABORT_END:			CleanupSubTransaction();			CommitTransactionCommand();			break;			/*			 * As above, but it's not dead yet, so abort first.			 */		case TBLOCK_SUBABORT_PENDING:			AbortSubTransaction();			CleanupSubTransaction();			CommitTransactionCommand();			break;			/*			 * The current subtransaction is the target of a ROLLBACK TO			 * command.  Abort and pop it, then start a new subtransaction			 * with the same name.			 */		case TBLOCK_SUBRESTART:			{				char	   *name;				int			savepointLevel;				/* save name and keep Cleanup from freeing it */				name = s->name;				s->name = NULL;				savepointLevel = s->savepointLevel;				AbortSubTransaction();				CleanupSubTransaction();				DefineSavepoint(NULL);				s = CurrentTransactionState;	/* changed by push */				s->name = name;				s->savepointLevel = savepointLevel;				/* This is the same as TBLOCK_SUBBEGIN case */				AssertState(s->blockState == TBLOCK_SUBBEGIN);				StartSubTransaction();				s->blockState = TBLOCK_SUBINPROGRESS;			}			break;			/*			 * Same as above, but the subtransaction had already failed, so we			 * don't need AbortSubTransaction.			 */		case TBLOCK_SUBABORT_RESTART:			{				char	   *name;				int			savepointLevel;				/* save name and keep Cleanup from freeing it */				name = s->name;				s->name = NULL;				savepointLevel = s->savepointLevel;				CleanupSubTransaction();				DefineSavepoint(NULL);				s = CurrentTransactionState;	/* changed by push */				s->name = name;				s->savepointLevel = savepointLevel;				/* This is the same as TBLOCK_SUBBEGIN case */				AssertState(s->blockState == TBLOCK_SUBBEGIN);				StartSubTransaction();				s->blockState = TBLOCK_SUBINPROGRESS;			}			break;	}}/* *	AbortCurrentTransaction */voidAbortCurrentTransaction(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{		case TBLOCK_DEFAULT:			if (s->state == TRANS_DEFAULT)			{				/* we are idle, so nothing to do */			}			else			{				/*				 * We can get here after an error during transaction start				 * (state will be TRANS_START).  Need to clean up the				 * incompletely started transaction.  First, adjust the				 * low-level state to suppress warning message from				 * AbortTransaction.				 */				if (s->state == TRANS_START)					s->state = TRANS_INPROGRESS;				AbortTransaction();				CleanupTransaction();			}			break;			/*			 * if we aren't in a transaction block, we just do the basic abort			 * & cleanup transaction.			 */		case TBLOCK_STARTED:			AbortTransaction();			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * If we are in TBLOCK_BEGIN it means something screwed up right			 * after reading "BEGIN TRANSACTION".  We assume that the user			 * will interpret the error as meaning the BEGIN failed to get him			 * into a transaction block, so we should abort and return to idle			 * state.			 */		case TBLOCK_BEGIN:			AbortTransaction();			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * We are somewhere in a transaction block and we've gotten a			 * failure, so we abort the transaction and set up the persistent			 * ABORT state.  We will stay in ABORT until we get a ROLLBACK.			 */		case TBLOCK_INPROGRESS:			AbortTransaction();			s->blockState = TBLOCK_ABORT;			/* CleanupTransaction happens when we exit TBLOCK_ABORT_END */			break;			/*			 * Here, we failed while trying to COMMIT.	Clean up the			 * transaction and return to idle state (we do not want to stay in			 * the transaction).			 */		case TBLOCK_END:			AbortTransaction();			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * Here, we are already in an aborted transaction state and are			 * waiting for a ROLLBACK, but for some reason we failed again! So			 * we just remain in the abort state.			 */		case TBLOCK_ABORT:		case TBLOCK_SUBABORT:			break;			/*			 * We are in a failed transaction and we got the ROLLBACK command.			 * We have already aborted, we just need to cleanup and go to idle			 * state.			 */		case TBLOCK_ABORT_END:			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * We are in a live transaction and we got a ROLLBACK command.			 * Abort, cleanup, go to idle state.			 */		case TBLOCK_ABORT_PENDING:			AbortTransaction();			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * Here, we failed while trying to PREPARE.  Clean up the			 * transaction and return to idle state (we do not want to stay in			 * the transaction).			 */		case TBLOCK_PREPARE:			AbortTransaction();			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * We got an error inside a subtransaction.  Abort just the			 * subtransaction, and go to the persistent SUBABORT state until			 * we get ROLLBACK.			 */		case TBLOCK_SUBINPROGRESS:			AbortSubTransaction();			s->blockState = TBLOCK_SUBABORT;			break;			/*			 * If we failed while trying to create a subtransaction, clean up			 * the broken subtransaction and abort the parent.	The same			 * applies if we get a failure while ending a subtransaction.			 */		case TBLOCK_SUBBEGIN:		case TBLOCK_SUBEND:		case TBLOCK_SUBABORT_PENDING:		case TBLOCK_SUBRESTART:			AbortSubTransaction();			CleanupSubTransaction();			AbortCurrentTransaction();			break;			/*			 * Same as above, except the Abort() was already done.			 */		case TBLOCK_SUBABORT_END:		case TBLOCK_SUBABORT_RESTART:			CleanupSubTransaction();			AbortCurrentTransaction();			break;	}}/* *	PreventTransactionChain * *	This routine is to be called by statements that must not run inside *	a transaction block, typically because they have non-rollback-able *	side effects or do internal commits. * *	If we have already started a transaction block, issue an error; also issue *	an error if we appear to be running inside a user-defined function (which *	could issue more commands and possibly cause a failure after the statement *	completes).  Subtransactions are verboten too. * *	stmtN

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?