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

📄 pquery.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * pquery.c *	  POSTGRES process query command code * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.97.2.1 2005/11/22 18:23:20 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "commands/prepare.h"#include "commands/trigger.h"#include "executor/executor.h"#include "miscadmin.h"#include "tcop/tcopprot.h"#include "tcop/pquery.h"#include "tcop/utility.h"#include "utils/guc.h"#include "utils/memutils.h"/* * ActivePortal is the currently executing Portal (the most closely nested, * if there are several). */Portal		ActivePortal = NULL;static void ProcessQuery(Query *parsetree,			 Plan *plan,			 ParamListInfo params,			 DestReceiver *dest,			 char *completionTag);static uint32 RunFromStore(Portal portal, ScanDirection direction, long count,			 DestReceiver *dest);static long PortalRunSelect(Portal portal, bool forward, long count,				DestReceiver *dest);static void PortalRunUtility(Portal portal, Query *query,				 DestReceiver *dest, char *completionTag);static void PortalRunMulti(Portal portal,			   DestReceiver *dest, DestReceiver *altdest,			   char *completionTag);static long DoPortalRunFetch(Portal portal,				 FetchDirection fdirection,				 long count,				 DestReceiver *dest);static void DoPortalRewind(Portal portal);/* * CreateQueryDesc */QueryDesc *CreateQueryDesc(Query *parsetree,				Plan *plantree,				Snapshot snapshot,				Snapshot crosscheck_snapshot,				DestReceiver *dest,				ParamListInfo params,				bool doInstrument){	QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));	qd->operation = parsetree->commandType;		/* operation */	qd->parsetree = parsetree;	/* parse tree */	qd->plantree = plantree;	/* plan */	qd->snapshot = snapshot;	/* snapshot */	qd->crosscheck_snapshot = crosscheck_snapshot;		/* RI check snapshot */	qd->dest = dest;			/* output dest */	qd->params = params;		/* parameter values passed into query */	qd->doInstrument = doInstrument;	/* instrumentation wanted? */	/* null these fields until set by ExecutorStart */	qd->tupDesc = NULL;	qd->estate = NULL;	qd->planstate = NULL;	return qd;}/* * FreeQueryDesc */voidFreeQueryDesc(QueryDesc *qdesc){	/* Can't be a live query */	Assert(qdesc->estate == NULL);	/* Only the QueryDesc itself need be freed */	pfree(qdesc);}/* * ProcessQuery *		Execute a single plannable query within a PORTAL_MULTI_QUERY portal * *	parsetree: the query tree *	plan: the plan tree for the query *	params: any parameters needed *	dest: where to send results *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE *		in which to store a command completion status string. * * completionTag may be NULL if caller doesn't want a status string. * * Must be called in a memory context that will be reset or deleted on * error; otherwise the executor's memory usage will be leaked. */static voidProcessQuery(Query *parsetree,			 Plan *plan,			 ParamListInfo params,			 DestReceiver *dest,			 char *completionTag){	int			operation = parsetree->commandType;	QueryDesc  *queryDesc;	ereport(DEBUG3,			(errmsg_internal("ProcessQuery")));	/*	 * Check for special-case destinations	 */	if (operation == CMD_SELECT)	{		if (parsetree->into != NULL)		{			/*			 * SELECT INTO table (a/k/a CREATE AS ... SELECT).			 *			 * Override the normal communication destination; execMain.c			 * special-cases this case.  (Perhaps would be cleaner to have an			 * additional destination type?)			 */			dest = None_Receiver;		}	}	/*	 * Must always set snapshot for plannable queries.	Note we assume that	 * caller will take care of restoring ActiveSnapshot on exit/error.	 */	ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());	/*	 * Create the QueryDesc object	 */	queryDesc = CreateQueryDesc(parsetree, plan,								ActiveSnapshot, InvalidSnapshot,								dest, params, false);	/*	 * Set up to collect AFTER triggers	 */	AfterTriggerBeginQuery();	/*	 * Call ExecStart to prepare the plan for execution	 */	ExecutorStart(queryDesc, false);	/*	 * Run the plan to completion.	 */	ExecutorRun(queryDesc, ForwardScanDirection, 0L);	/*	 * Build command completion status string, if caller wants one.	 */	if (completionTag)	{		Oid			lastOid;		switch (operation)		{			case CMD_SELECT:				strcpy(completionTag, "SELECT");				break;			case CMD_INSERT:				if (queryDesc->estate->es_processed == 1)					lastOid = queryDesc->estate->es_lastoid;				else					lastOid = InvalidOid;				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,				   "INSERT %u %u", lastOid, queryDesc->estate->es_processed);				break;			case CMD_UPDATE:				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,						 "UPDATE %u", queryDesc->estate->es_processed);				break;			case CMD_DELETE:				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,						 "DELETE %u", queryDesc->estate->es_processed);				break;			default:				strcpy(completionTag, "???");				break;		}	}	/* Now take care of any queued AFTER triggers */	AfterTriggerEndQuery(queryDesc->estate);	/*	 * Now, we close down all the scans and free allocated resources.	 */	ExecutorEnd(queryDesc);	FreeQueryDesc(queryDesc);	FreeSnapshot(ActiveSnapshot);	ActiveSnapshot = NULL;}/* * ChoosePortalStrategy *		Select portal execution strategy given the intended query list. * * See the comments in portal.h. */PortalStrategyChoosePortalStrategy(List *parseTrees){	PortalStrategy strategy;	strategy = PORTAL_MULTI_QUERY;		/* default assumption */	if (list_length(parseTrees) == 1)	{		Query	   *query = (Query *) linitial(parseTrees);		if (query->commandType == CMD_SELECT &&			query->canSetTag &&			query->into == NULL)			strategy = PORTAL_ONE_SELECT;		else if (query->commandType == CMD_UTILITY &&				 query->canSetTag &&				 query->utilityStmt != NULL)		{			if (UtilityReturnsTuples(query->utilityStmt))				strategy = PORTAL_UTIL_SELECT;		}	}	return strategy;}/* * FetchPortalTargetList *		Given a portal that returns tuples, extract the query targetlist. *		Returns NIL if the portal doesn't have a determinable targetlist. * * Note: do not modify the result. * * XXX be careful to keep this in sync with FetchPreparedStatementTargetList, * and with UtilityReturnsTuples. */List *FetchPortalTargetList(Portal portal){	if (portal->strategy == PORTAL_ONE_SELECT)		return ((Query *) linitial(portal->parseTrees))->targetList;	if (portal->strategy == PORTAL_UTIL_SELECT)	{		Node	   *utilityStmt;		utilityStmt = ((Query *) linitial(portal->parseTrees))->utilityStmt;		switch (nodeTag(utilityStmt))		{			case T_FetchStmt:				{					FetchStmt  *substmt = (FetchStmt *) utilityStmt;					Portal		subportal;					Assert(!substmt->ismove);					subportal = GetPortalByName(substmt->portalname);					Assert(PortalIsValid(subportal));					return FetchPortalTargetList(subportal);				}			case T_ExecuteStmt:				{					ExecuteStmt *substmt = (ExecuteStmt *) utilityStmt;					PreparedStatement *entry;					Assert(!substmt->into);					entry = FetchPreparedStatement(substmt->name, true);					return FetchPreparedStatementTargetList(entry);				}			default:				break;		}	}	return NIL;}/* * PortalStart *		Prepare a portal for execution. * * Caller must already have created the portal, done PortalDefineQuery(), * and adjusted portal options if needed.  If parameters are needed by * the query, they must be passed in here (caller is responsible for * giving them appropriate lifetime). * * The caller can optionally pass a snapshot to be used; pass InvalidSnapshot * for the normal behavior of setting a new snapshot.  This parameter is * presently ignored for non-PORTAL_ONE_SELECT portals (it's only intended * to be used for cursors). * * On return, portal is ready to accept PortalRun() calls, and the result * tupdesc (if any) is known. */voidPortalStart(Portal portal, ParamListInfo params, Snapshot snapshot){	Portal		saveActivePortal;	Snapshot	saveActiveSnapshot;	ResourceOwner saveResourceOwner;	MemoryContext savePortalContext;	MemoryContext oldContext;	QueryDesc  *queryDesc;	AssertArg(PortalIsValid(portal));	AssertState(portal->queryContext != NULL);	/* query defined? */	AssertState(portal->status == PORTAL_NEW);	/* else extra PortalStart */	/*	 * Set up global portal context pointers.  (Should we set QueryContext?)	 */	saveActivePortal = ActivePortal;	saveActiveSnapshot = ActiveSnapshot;	saveResourceOwner = CurrentResourceOwner;	savePortalContext = PortalContext;	PG_TRY();	{		ActivePortal = portal;		ActiveSnapshot = NULL;	/* will be set later */		CurrentResourceOwner = portal->resowner;		PortalContext = PortalGetHeapMemory(portal);		oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));		/* Must remember portal param list, if any */		portal->portalParams = params;		/*		 * Determine the portal execution strategy		 */		portal->strategy = ChoosePortalStrategy(portal->parseTrees);		/*		 * Fire her up according to the strategy		 */		switch (portal->strategy)		{			case PORTAL_ONE_SELECT:				/*				 * Must set snapshot before starting executor.	Be sure to				 * copy it into the portal's context.				 */				if (snapshot)					ActiveSnapshot = CopySnapshot(snapshot);				else					ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());				/*				 * Create QueryDesc in portal's context; for the moment, set				 * the destination to DestNone.				 */				queryDesc = CreateQueryDesc((Query *) linitial(portal->parseTrees),										(Plan *) linitial(portal->planTrees),											ActiveSnapshot,											InvalidSnapshot,											None_Receiver,											params,											false);				/*				 * We do *not* call AfterTriggerBeginQuery() here.	We assume				 * that a SELECT cannot queue any triggers.  It would be messy				 * to support triggers since the execution of the portal may				 * be interleaved with other queries.				 */				/*				 * Call ExecStart to prepare the plan for execution				 */				ExecutorStart(queryDesc, false);				/*				 * This tells PortalCleanup to shut down the executor				 */				portal->queryDesc = queryDesc;				/*				 * Remember tuple descriptor (computed by ExecutorStart)				 */				portal->tupDesc = queryDesc->tupDesc;				/*				 * Reset cursor position data to "start of query"				 */				portal->atStart = true;				portal->atEnd = false;	/* allow fetches */				portal->portalPos = 0;				portal->posOverflow = false;				break;			case PORTAL_UTIL_SELECT:				/*				 * We don't set snapshot here, because PortalRunUtility will				 * take care of it if needed.				 */				portal->tupDesc =					UtilityTupleDescriptor(((Query *) linitial(portal->parseTrees))->utilityStmt);				/*				 * Reset cursor position data to "start of query"				 */				portal->atStart = true;				portal->atEnd = false;	/* allow fetches */				portal->portalPos = 0;				portal->posOverflow = false;				break;			case PORTAL_MULTI_QUERY:				/* Need do nothing now */				portal->tupDesc = NULL;				break;		}	}	PG_CATCH();	{		/* Uncaught error while executing portal: mark it dead */		portal->status = PORTAL_FAILED;		/* Restore global vars and propagate error */		ActivePortal = saveActivePortal;		ActiveSnapshot = saveActiveSnapshot;		CurrentResourceOwner = saveResourceOwner;		PortalContext = savePortalContext;		PG_RE_THROW();	}	PG_END_TRY();	MemoryContextSwitchTo(oldContext);	ActivePortal = saveActivePortal;	ActiveSnapshot = saveActiveSnapshot;	CurrentResourceOwner = saveResourceOwner;	PortalContext = savePortalContext;	portal->status = PORTAL_READY;}/* * PortalSetResultFormat *		Select the format codes for a portal's output. * * This must be run after PortalStart for a portal that will be read by * a DestRemote or DestRemoteExecute destination.  It is not presently needed * for other destination types. * * formats[] is the client format request, as per Bind message conventions. */void

⌨️ 快捷键说明

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