⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xact.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),		/* translator: %s represents an SQL statement name */				 errmsg("%s cannot run inside a transaction block",						stmtType)));	/*	 * Are we inside a function call?  If the statement's parameter block	 * was allocated in QueryContext, assume it is an interactive command.	 * Otherwise assume it is coming from a function.	 */	if (!MemoryContextContains(QueryContext, stmtNode))		ereport(ERROR,				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),		/* translator: %s represents an SQL statement name */			 errmsg("%s cannot be executed from a function", stmtType)));	/* If we got past IsTransactionBlock test, should be in default state */	if (CurrentTransactionState->blockState != TBLOCK_DEFAULT)		elog(ERROR, "cannot prevent transaction chain");	/* all okay */}/* *	RequireTransactionChain * *	This routine is to be called by statements that must run inside *	a transaction block, because they have no effects that persist past *	transaction end (and so calling them outside a transaction block *	is presumably an error).  DECLARE CURSOR is an example. * *	If we appear to be running inside a user-defined function, we do not *	issue an error, since the function could issue more commands that make *	use of the current statement's results.  Thus this is an inverse for *	PreventTransactionChain. * *	stmtNode: pointer to parameter block for statement; this is used in *	a very klugy way to determine whether we are inside a function. *	stmtType: statement type name for error messages. */voidRequireTransactionChain(void *stmtNode, const char *stmtType){	/*	 * xact block already started?	 */	if (IsTransactionBlock())		return;	/*	 * Are we inside a function call?  If the statement's parameter block	 * was allocated in QueryContext, assume it is an interactive command.	 * Otherwise assume it is coming from a function.	 */	if (!MemoryContextContains(QueryContext, stmtNode))		return;	ereport(ERROR,			(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),	/* translator: %s represents an SQL statement name */			 errmsg("%s may only be used in transaction blocks",					stmtType)));}/* * Register or deregister callback functions for end-of-xact cleanup * * These functions are intended for use by dynamically loaded modules. * For built-in modules we generally just hardwire the appropriate calls * (mainly because it's easier to control the order that way, where needed). * * Note that the callback occurs post-commit or post-abort, so the callback * functions can only do noncritical cleanup. */voidRegisterEOXactCallback(EOXactCallback callback, void *arg){	EOXactCallbackItem *item;	item = (EOXactCallbackItem *)		MemoryContextAlloc(TopMemoryContext, sizeof(EOXactCallbackItem));	item->callback = callback;	item->arg = arg;	item->next = EOXact_callbacks;	EOXact_callbacks = item;}voidUnregisterEOXactCallback(EOXactCallback callback, void *arg){	EOXactCallbackItem *item;	EOXactCallbackItem *prev;	prev = NULL;	for (item = EOXact_callbacks; item; prev = item, item = item->next)	{		if (item->callback == callback && item->arg == arg)		{			if (prev)				prev->next = item->next;			else				EOXact_callbacks = item->next;			pfree(item);			break;		}	}}static voidCallEOXactCallbacks(bool isCommit){	EOXactCallbackItem *item;	for (item = EOXact_callbacks; item; item = item->next)	{		(*item->callback) (isCommit, item->arg);	}}/* ---------------------------------------------------------------- *					   transaction block support * ---------------------------------------------------------------- *//* *	BeginTransactionBlock */voidBeginTransactionBlock(void){	TransactionState s = CurrentTransactionState;	/*	 * check the current transaction state	 */	if (s->blockState != TBLOCK_DEFAULT)		ereport(WARNING,				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),				 errmsg("there is already a transaction in progress")));	/*	 * set the current transaction block state information appropriately	 * during begin processing	 */	s->blockState = TBLOCK_BEGIN;	/*	 * do begin processing here.  Nothing to do at present.	 */	/*	 * done with begin processing, set block state to inprogress	 */	s->blockState = TBLOCK_INPROGRESS;}/* *	EndTransactionBlock */voidEndTransactionBlock(void){	TransactionState s = CurrentTransactionState;	/*	 * check the current transaction state	 */	if (s->blockState == TBLOCK_INPROGRESS)	{		/*		 * here we are in a transaction block which should commit when we		 * get to the upcoming CommitTransactionCommand() so we set the		 * state to "END".	CommitTransactionCommand() will recognize this		 * and commit the transaction and return us to the default state		 */		s->blockState = TBLOCK_END;		return;	}	if (s->blockState == TBLOCK_ABORT)	{		/*		 * here, we are in a transaction block which aborted and since the		 * AbortTransaction() was already done, we do whatever is needed		 * and change to the special "END ABORT" state.  The upcoming		 * CommitTransactionCommand() will recognise this and then put us		 * back in the default state.		 */		s->blockState = TBLOCK_ENDABORT;		return;	}	/*	 * here, the user issued COMMIT when not inside a transaction. Issue a	 * WARNING and go to abort state.  The upcoming call to	 * CommitTransactionCommand() will then put us back into the default	 * state.	 */	ereport(WARNING,			(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),			 errmsg("there is no transaction in progress")));	AbortTransaction();	s->blockState = TBLOCK_ENDABORT;}/* *	AbortTransactionBlock */#ifdef NOT_USEDstatic voidAbortTransactionBlock(void){	TransactionState s = CurrentTransactionState;	/*	 * check the current transaction state	 */	if (s->blockState == TBLOCK_INPROGRESS)	{		/*		 * here we were inside a transaction block something screwed up		 * inside the system so we enter the abort state, do the abort		 * processing and then return. We remain in the abort state until		 * we see an END TRANSACTION command.		 */		s->blockState = TBLOCK_ABORT;		AbortTransaction();		return;	}	/*	 * here, the user issued ABORT when not inside a transaction. Issue a	 * WARNING and go to abort state.  The upcoming call to	 * CommitTransactionCommand() will then put us back into the default	 * state.	 */	ereport(WARNING,			(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),			 errmsg("there is no transaction in progress")));	AbortTransaction();	s->blockState = TBLOCK_ENDABORT;}#endif/* *	UserAbortTransactionBlock */voidUserAbortTransactionBlock(void){	TransactionState s = CurrentTransactionState;	/*	 * if the transaction has already been automatically aborted with an	 * error, and the user subsequently types 'abort', allow it.  (the	 * behavior is the same as if they had typed 'end'.)	 */	if (s->blockState == TBLOCK_ABORT)	{		s->blockState = TBLOCK_ENDABORT;		return;	}	if (s->blockState == TBLOCK_INPROGRESS)	{		/*		 * here we were inside a transaction block and we got an abort		 * command from the user, so we move to the abort state, do the		 * abort processing and then change to the ENDABORT state so we		 * will end up in the default state after the upcoming		 * CommitTransactionCommand().		 */		s->blockState = TBLOCK_ABORT;		AbortTransaction();		s->blockState = TBLOCK_ENDABORT;		return;	}	/*	 * here, the user issued ABORT when not inside a transaction. Issue a	 * WARNING and go to abort state.  The upcoming call to	 * CommitTransactionCommand() will then put us back into the default	 * state.	 */	ereport(WARNING,			(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),			 errmsg("there is no transaction in progress")));	AbortTransaction();	s->blockState = TBLOCK_ENDABORT;}/* *	AbortOutOfAnyTransaction * *	This routine is provided for error recovery purposes.  It aborts any *	active transaction or transaction block, leaving the system in a known *	idle state. */voidAbortOutOfAnyTransaction(void){	TransactionState s = CurrentTransactionState;	/*	 * Get out of any low-level transaction	 */	switch (s->state)	{		case TRANS_START:		case TRANS_INPROGRESS:		case TRANS_COMMIT:			/* In a transaction, so clean up */			AbortTransaction();			CleanupTransaction();			break;		case TRANS_ABORT:			/* AbortTransaction already done, still need Cleanup */			CleanupTransaction();			break;		case TRANS_DEFAULT:			/* Not in a transaction, do nothing */			break;	}	/*	 * Now reset the high-level state	 */	s->blockState = TBLOCK_DEFAULT;}/* * IsTransactionBlock --- are we within a transaction block? */boolIsTransactionBlock(void){	TransactionState s = CurrentTransactionState;	if (s->blockState == TBLOCK_DEFAULT)		return false;	return true;}/* * IsTransactionOrTransactionBlock --- are we within either a transaction * or a transaction block?  (The backend is only really "idle" when this * returns false.) * * This should match up with IsTransactionBlock and IsTransactionState. */boolIsTransactionOrTransactionBlock(void){	TransactionState s = CurrentTransactionState;	if (s->blockState == TBLOCK_DEFAULT && s->state == TRANS_DEFAULT)		return false;	return true;}/* * TransactionBlockStatusCode - return status code to send in ReadyForQuery */charTransactionBlockStatusCode(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{		case TBLOCK_DEFAULT:			return 'I';			/* idle --- not in transaction */		case TBLOCK_BEGIN:		case TBLOCK_INPROGRESS:		case TBLOCK_END:			return 'T';			/* in transaction */		case TBLOCK_ABORT:		case TBLOCK_ENDABORT:			return 'E';			/* in failed transaction */	}	/* should never get here */	elog(ERROR, "invalid transaction block state: %d",		 (int) s->blockState);	return 0;					/* keep compiler quiet */}/* *	XLOG support routines */voidxact_redo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	if (info == XLOG_XACT_COMMIT)	{		TransactionIdCommit(record->xl_xid);		/* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */	}	else if (info == XLOG_XACT_ABORT)	{		TransactionIdAbort(record->xl_xid);		/* SHOULD REMOVE FILES OF ALL FAILED-TO-BE-CREATED RELATIONS */	}	else		elog(PANIC, "xact_redo: unknown op code %u", info);}voidxact_undo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	if (info == XLOG_XACT_COMMIT)		/* shouldn't be called by XLOG */		elog(PANIC, "xact_undo: can't undo committed xaction");	else if (info != XLOG_XACT_ABORT)		elog(PANIC, "xact_redo: unknown op code %u", info);}voidxact_desc(char *buf, uint8 xl_info, char *rec){	uint8		info = xl_info & ~XLR_INFO_MASK;	if (info == XLOG_XACT_COMMIT)	{		xl_xact_commit *xlrec = (xl_xact_commit *) rec;		struct tm  *tm = localtime(&xlrec->xtime);		sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",				tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,				tm->tm_hour, tm->tm_min, tm->tm_sec);	}	else if (info == XLOG_XACT_ABORT)	{		xl_xact_abort *xlrec = (xl_xact_abort *) rec;		struct tm  *tm = localtime(&xlrec->xtime);		sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",				tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,				tm->tm_hour, tm->tm_min, tm->tm_sec);	}	else		strcat(buf, "UNKNOWN");}void			XactPushRollback(void (*func) (void *), void *data){#ifdef XLOG_II	if (_RollbackFunc != NULL)		elog(PANIC, "XactPushRollback: already installed");#endif	_RollbackFunc = func;	_RollbackData = data;}voidXactPopRollback(void){	_RollbackFunc = NULL;}

⌨️ 快捷键说明

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