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

📄 prepare.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	oldcxt = MemoryContextSwitchTo(entrycxt);	/*	 * We need to copy the data so that it is stored in the correct memory	 * context.  Do this before making hashtable entry, so that an	 * out-of-memory failure only wastes memory and doesn't leave us with an	 * incomplete (ie corrupt) hashtable entry.	 */	qstring = query_string ? pstrdup(query_string) : NULL;	query_list = (List *) copyObject(query_list);	plan_list = (List *) copyObject(plan_list);	argtype_list = list_copy(argtype_list);	/* Now we can add entry to hash table */	entry = (PreparedStatement *) hash_search(prepared_queries,											  key,											  HASH_ENTER,											  &found);	/* Shouldn't get a duplicate entry */	if (found)		elog(ERROR, "duplicate prepared statement \"%s\"",			 stmt_name);	/* Fill in the hash table entry with copied data */	entry->query_string = qstring;	entry->commandTag = commandTag;	entry->query_list = query_list;	entry->plan_list = plan_list;	entry->argtype_list = argtype_list;	entry->context = entrycxt;	MemoryContextSwitchTo(oldcxt);}/* * Lookup an existing query in the hash table. If the query does not * actually exist, throw ereport(ERROR) or return NULL per second parameter. */PreparedStatement *FetchPreparedStatement(const char *stmt_name, bool throwError){	char		key[NAMEDATALEN];	PreparedStatement *entry;	/*	 * If the hash table hasn't been initialized, it can't be storing	 * anything, therefore it couldn't possibly store our plan.	 */	if (prepared_queries)	{		/*		 * We can't just use the statement name as supplied by the user: the		 * hash package is picky enough that it needs to be NULL-padded out to		 * the appropriate length to work correctly.		 */		StrNCpy(key, stmt_name, sizeof(key));		entry = (PreparedStatement *) hash_search(prepared_queries,												  key,												  HASH_FIND,												  NULL);	}	else		entry = NULL;	if (!entry && throwError)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_PSTATEMENT),				 errmsg("prepared statement \"%s\" does not exist",						stmt_name)));	return entry;}/* * Look up a prepared statement given the name (giving error if not found). * If found, return the list of argument type OIDs. */List *FetchPreparedStatementParams(const char *stmt_name){	PreparedStatement *entry;	entry = FetchPreparedStatement(stmt_name, true);	return entry->argtype_list;}/* * Given a prepared statement, determine the result tupledesc it will * produce.  Returns NULL if the execution will not return tuples. * * Note: the result is created or copied into current memory context. */TupleDescFetchPreparedStatementResultDesc(PreparedStatement *stmt){	Query	   *query;	switch (ChoosePortalStrategy(stmt->query_list))	{		case PORTAL_ONE_SELECT:			query = (Query *) linitial(stmt->query_list);			return ExecCleanTypeFromTL(query->targetList, false);		case PORTAL_UTIL_SELECT:			query = (Query *) linitial(stmt->query_list);			return UtilityTupleDescriptor(query->utilityStmt);		case PORTAL_MULTI_QUERY:			/* will not return tuples */			break;	}	return NULL;}/* * Given a prepared statement, determine whether it will return tuples. * * Note: this is used rather than just testing the result of * FetchPreparedStatementResultDesc() because that routine can fail if * invoked in an aborted transaction.  This one is safe to use in any * context.  Be sure to keep the two routines in sync! */boolPreparedStatementReturnsTuples(PreparedStatement *stmt){	switch (ChoosePortalStrategy(stmt->query_list))	{		case PORTAL_ONE_SELECT:		case PORTAL_UTIL_SELECT:			return true;		case PORTAL_MULTI_QUERY:			/* will not return tuples */			break;	}	return false;}/* * Given a prepared statement that returns tuples, extract the query * targetlist.	Returns NIL if the statement doesn't have a determinable * targetlist. * * Note: do not modify the result. * * XXX be careful to keep this in sync with FetchPortalTargetList, * and with UtilityReturnsTuples. */List *FetchPreparedStatementTargetList(PreparedStatement *stmt){	PortalStrategy strategy = ChoosePortalStrategy(stmt->query_list);	if (strategy == PORTAL_ONE_SELECT)		return ((Query *) linitial(stmt->query_list))->targetList;	if (strategy == PORTAL_UTIL_SELECT)	{		Node	   *utilityStmt;		utilityStmt = ((Query *) linitial(stmt->query_list))->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;}/* * Implements the 'DEALLOCATE' utility statement: deletes the * specified plan from storage. */voidDeallocateQuery(DeallocateStmt *stmt){	DropPreparedStatement(stmt->name, true);}/* * Internal version of DEALLOCATE * * If showError is false, dropping a nonexistent statement is a no-op. */voidDropPreparedStatement(const char *stmt_name, bool showError){	PreparedStatement *entry;	/* Find the query's hash table entry; raise error if wanted */	entry = FetchPreparedStatement(stmt_name, showError);	if (entry)	{		/* Drop any open portals that depend on this prepared statement */		Assert(MemoryContextIsValid(entry->context));		DropDependentPortals(entry->context);		/* Flush the context holding the subsidiary data */		MemoryContextDelete(entry->context);		/* Now we can remove the hash table entry */		hash_search(prepared_queries, entry->stmt_name, HASH_REMOVE, NULL);	}}/* * Implements the 'EXPLAIN EXECUTE' utility statement. */voidExplainExecuteQuery(ExplainStmt *stmt, TupOutputState *tstate){	ExecuteStmt *execstmt = (ExecuteStmt *) stmt->query->utilityStmt;	PreparedStatement *entry;	ListCell   *q,			   *p;	List	   *query_list,			   *plan_list;	ParamListInfo paramLI = NULL;	EState	   *estate = NULL;	/* explain.c should only call me for EXECUTE stmt */	Assert(execstmt && IsA(execstmt, ExecuteStmt));	/* Look it up in the hash table */	entry = FetchPreparedStatement(execstmt->name, true);	query_list = entry->query_list;	plan_list = entry->plan_list;	Assert(list_length(query_list) == list_length(plan_list));	/* Evaluate parameters, if any */	if (entry->argtype_list != NIL)	{		/*		 * Need an EState to evaluate parameters; must not delete it till end		 * of query, in case parameters are pass-by-reference.		 */		estate = CreateExecutorState();		paramLI = EvaluateParams(estate, execstmt->params,								 entry->argtype_list);	}	/* Explain each query */	forboth(q, query_list, p, plan_list)	{		Query	   *query = (Query *) lfirst(q);		Plan	   *plan = (Plan *) lfirst(p);		bool		is_last_query;		is_last_query = (lnext(p) == NULL);		if (query->commandType == CMD_UTILITY)		{			if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))				do_text_output_oneline(tstate, "NOTIFY");			else				do_text_output_oneline(tstate, "UTILITY");		}		else		{			QueryDesc  *qdesc;			if (execstmt->into)			{				if (query->commandType != CMD_SELECT)					ereport(ERROR,							(errcode(ERRCODE_WRONG_OBJECT_TYPE),							 errmsg("prepared statement is not a SELECT")));				/* Copy the query so we can modify it */				query = copyObject(query);				query->into = execstmt->into;			}			/*			 * Update snapshot command ID to ensure this query sees results of			 * any previously executed queries.  (It's a bit cheesy to modify			 * ActiveSnapshot without making a copy, but for the limited ways			 * in which EXPLAIN can be invoked, I think it's OK, because the			 * active snapshot shouldn't be shared with anything else anyway.)			 */			ActiveSnapshot->curcid = GetCurrentCommandId();			/* Create a QueryDesc requesting no output */			qdesc = CreateQueryDesc(query, plan,									ActiveSnapshot, InvalidSnapshot,									None_Receiver,									paramLI, stmt->analyze);			ExplainOnePlan(qdesc, stmt, tstate);		}		/* No need for CommandCounterIncrement, as ExplainOnePlan did it */		/* put a blank line between plans */		if (!is_last_query)			do_text_output_oneline(tstate, "");	}	if (estate)		FreeExecutorState(estate);}

⌨️ 快捷键说明

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