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

📄 fcache.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * fcache.c *	  Code for the 'function cache' used in Oper and Func nodes.... * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/cache/fcache.c,v 1.22 1999/05/10 00:46:06 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <nodes/parsenodes.h>#include <fmgr.h>#include "access/htup.h"#include "utils/catcache.h"#include "utils/syscache.h"#include "catalog/pg_type.h"#include "catalog/pg_proc.h"#include "catalog/pg_language.h"#include "catalog/pg_class.h"#include "parser/parsetree.h"	/* for getrelname() */#include "utils/builtins.h"#include "utils/fcache.h"#include "utils/fcache2.h"#include "nodes/primnodes.h"#include "nodes/execnodes.h"#ifndef HAVE_MEMMOVE#include <regex/utils.h>#else#include <string.h>#endifstatic Oid	GetDynamicFuncArgType(Var *arg, ExprContext *econtext);static FunctionCachePtr init_fcache(Oid foid,			bool use_syscache,			List *argList,			ExprContext *econtext);/*----------------------------------------------------------------- * * Initialize the 'FunctionCache' given the PG_PROC oid. * * * NOTE:  This function can be called when the system cache is being *		  initialized.	Therefore, use_syscache should ONLY be true *		  when the function return type is interesting (ie: set_fcache). *----------------------------------------------------------------- */#define FuncArgTypeIsDynamic(arg) \	(IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber)static OidGetDynamicFuncArgType(Var *arg, ExprContext *econtext){	char	   *relname;	int			rtid;	HeapTuple	tup;	Assert(IsA(arg, Var));	rtid = ((Var *) arg)->varno;	relname = (char *) getrelname(rtid, econtext->ecxt_range_table);	tup = SearchSysCacheTuple(TYPNAME,							  PointerGetDatum(relname),							  0, 0, 0);	if (!tup)		elog(ERROR, "Lookup failed on type tuple for class %s",			 relname);	return tup->t_data->t_oid;}static FunctionCachePtrinit_fcache(Oid foid,			bool use_syscache,			List *argList,			ExprContext *econtext){	HeapTuple	procedureTuple;	HeapTuple	typeTuple;	Form_pg_proc procedureStruct;	Form_pg_type typeStruct;	FunctionCachePtr retval;	text	   *tmp;	int			nargs;	/* ----------------	 *	 get the procedure tuple corresponding to the given	 *	 functionOid.  If this fails, returnValue has been	 *	 pre-initialized to "null" so we just return it.	 * ----------------	 */	retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));	memset(retval, 0, sizeof(FunctionCache));	if (!use_syscache)		elog(ERROR, "what the ????, init the fcache without the catalogs?");	procedureTuple = SearchSysCacheTuple(PROOID,										 ObjectIdGetDatum(foid),										 0, 0, 0);	if (!HeapTupleIsValid(procedureTuple))		elog(ERROR,			 "init_fcache: %s %u",			 "Cache lookup failed for procedure", foid);	/* ----------------	 *	 get the return type from the procedure tuple	 * ----------------	 */	procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);	/* ----------------	 *	 get the type tuple corresponding to the return type	 *	 If this fails, returnValue has been pre-initialized	 *	 to "null" so we just return it.	 * ----------------	 */	typeTuple = SearchSysCacheTuple(TYPOID,						   ObjectIdGetDatum(procedureStruct->prorettype),									0, 0, 0);	if (!HeapTupleIsValid(typeTuple))		elog(ERROR,			 "init_fcache: %s %u",			 "Cache lookup failed for type",			 (procedureStruct)->prorettype);	/* ----------------	 *	 get the type length and by-value from the type tuple and	 *	 save the information in our one element cache.	 * ----------------	 */	typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);	retval->typlen = (typeStruct)->typlen;	if ((typeStruct)->typrelid == InvalidOid)	{		/* The return type is not a relation, so just use byval */		retval->typbyval = (typeStruct)->typbyval ? true : false;	}	else	{		/*		 * This is a hack.	We assume here that any function returning a		 * relation returns it by reference.  This needs to be fixed.		 */		retval->typbyval = false;	}	retval->foid = foid;	retval->language = procedureStruct->prolang;	retval->func_state = (char *) NULL;	retval->setArg = NULL;	retval->hasSetArg = false;	retval->oneResult = !procedureStruct->proretset;	retval->istrusted = procedureStruct->proistrusted;	/*	 * If we are returning exactly one result then we have to copy tuples	 * and by reference results because we have to end the execution	 * before we return the results.  When you do this everything	 * allocated by the executor (i.e. slots and tuples) is freed.	 */	if ((retval->language == SQLlanguageId) &&		(retval->oneResult) &&		!(retval->typbyval))	{		Form_pg_class relationStruct;		HeapTuple	relationTuple;		TupleDesc	td;		TupleTableSlot *slot;		slot = makeNode(TupleTableSlot);		slot->ttc_shouldFree = true;		slot->ttc_descIsNew = true;		slot->ttc_tupleDescriptor = (TupleDesc) NULL;		slot->ttc_buffer = InvalidBuffer;		slot->ttc_whichplan = -1;		retval->funcSlot = (Pointer) slot;		relationTuple = (HeapTuple)			SearchSysCacheTuple(RELNAME,								PointerGetDatum(&typeStruct->typname),								0, 0, 0);		if (relationTuple)		{			relationStruct = (Form_pg_class) GETSTRUCT(relationTuple);			td = CreateTemplateTupleDesc(relationStruct->relnatts);		}		else			td = CreateTemplateTupleDesc(1);		((TupleTableSlot *) retval->funcSlot)->ttc_tupleDescriptor = td;	}	else		retval->funcSlot = (char *) NULL;	nargs = procedureStruct->pronargs;	retval->nargs = nargs;	if (nargs > 0)	{		Oid		   *argTypes;		retval->nullVect = (bool *) palloc((retval->nargs) * sizeof(bool));		if (retval->language == SQLlanguageId)		{			int			i;			List	   *oneArg;			retval->argOidVect = (Oid *) palloc(retval->nargs * sizeof(Oid));			argTypes = procedureStruct->proargtypes;			memmove(retval->argOidVect,					argTypes,					(retval->nargs) * sizeof(Oid));			for (i = 0;				 argList;				 i++, argList = lnext(argList))			{				oneArg = lfirst(argList);				if (FuncArgTypeIsDynamic(oneArg))					retval->argOidVect[i] = GetDynamicFuncArgType((Var *) oneArg,															   econtext);			}		}		else			retval->argOidVect = (Oid *) NULL;	}	else	{		retval->argOidVect = (Oid *) NULL;		retval->nullVect = (BoolPtr) NULL;	}	/*	 * XXX this is the first varlena in the struct.  If the order changes	 * for some reason this will fail.	 */	if (procedureStruct->prolang == SQLlanguageId)	{		retval->src = textout(&(procedureStruct->prosrc));		retval->bin = (char *) NULL;	}	else	{		/*		 * I'm not sure that we even need to do this at all.		 */		/*		 * We do for untrusted functions.		 */		if (procedureStruct->proistrusted)			retval->bin = (char *) NULL;		else		{			tmp = (text *)				SearchSysCacheGetAttribute(PROOID,										   Anum_pg_proc_probin,										   ObjectIdGetDatum(foid),										   0, 0, 0);			retval->bin = textout(tmp);		}		retval->src = (char *) NULL;	}	if (retval->language != SQLlanguageId)	{		fmgr_info(foid, &(retval->func));		retval->nargs = retval->func.fn_nargs;	}	else		retval->func.fn_addr = (func_ptr) NULL;	return retval;}voidsetFcache(Node *node, Oid foid, List *argList, ExprContext *econtext){	Func	   *fnode;	Oper	   *onode;	FunctionCachePtr fcache;	fcache = init_fcache(foid, true, argList, econtext);	if (IsA(node, Oper))	{		onode = (Oper *) node;		onode->op_fcache = fcache;	}	else if (IsA(node, Func))	{		fnode = (Func *) node;		fnode->func_fcache = fcache;	}	else		elog(ERROR, "init_fcache: node must be Oper or Func!");}

⌨️ 快捷键说明

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