diff options
Diffstat (limited to 'src/backend/utils/cache/fcache.c')
-rw-r--r-- | src/backend/utils/cache/fcache.c | 481 |
1 files changed, 246 insertions, 235 deletions
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c index 1d86364abda..ad174c6fdf5 100644 --- a/src/backend/utils/cache/fcache.c +++ b/src/backend/utils/cache/fcache.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fcache.c-- - * Code for the 'function cache' used in Oper and Func nodes.... + * Code for the 'function cache' used in Oper and Func nodes.... * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.4 1996/11/10 03:03:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.5 1997/09/07 04:52:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,23 +23,24 @@ #include "catalog/pg_proc.h" #include "catalog/pg_language.h" #include "catalog/pg_class.h" -#include "parser/parsetree.h" /* for getrelname() */ +#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> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif -static Oid GetDynamicFuncArgType(Var *arg, ExprContext *econtext); -static FunctionCachePtr init_fcache(Oid foid, - bool use_syscache, - List *argList, - ExprContext *econtext); +static Oid GetDynamicFuncArgType(Var * arg, ExprContext * econtext); +static FunctionCachePtr +init_fcache(Oid foid, + bool use_syscache, + List * argList, + ExprContext * econtext); /*----------------------------------------------------------------- * @@ -47,259 +48,269 @@ static FunctionCachePtr init_fcache(Oid foid, * * * 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). + * 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) + (IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber) -static Oid -GetDynamicFuncArgType(Var *arg, ExprContext *econtext) +static Oid +GetDynamicFuncArgType(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(WARN, "Lookup failed on type tuple for class %s", - relname); - - return tup->t_oid; + 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(WARN, "Lookup failed on type tuple for class %s", + relname); + + return tup->t_oid; } -static FunctionCachePtr +static FunctionCachePtr init_fcache(Oid foid, - bool use_syscache, - List *argList, - ExprContext *econtext) + bool use_syscache, + List * argList, + ExprContext * econtext) { - HeapTuple procedureTuple; - HeapTuple typeTuple; - Form_pg_proc procedureStruct; - TypeTupleForm 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)); - - if (!use_syscache) - elog(WARN, "what the ????, init the fcache without the catalogs?"); - - procedureTuple = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(foid), - 0,0,0); - - if (!HeapTupleIsValid(procedureTuple)) - elog(WARN, - "init_fcache: %s %d", - "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(WARN, - "init_fcache: %s %d", - "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 = (TypeTupleForm) 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. + HeapTuple procedureTuple; + HeapTuple typeTuple; + Form_pg_proc procedureStruct; + TypeTupleForm 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)); + + if (!use_syscache) + elog(WARN, "what the ????, init the fcache without the catalogs?"); + + procedureTuple = SearchSysCacheTuple(PROOID, + ObjectIdGetDatum(foid), + 0, 0, 0); + + if (!HeapTupleIsValid(procedureTuple)) + elog(WARN, + "init_fcache: %s %d", + "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(WARN, + "init_fcache: %s %d", + "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. + * ---------------- */ - 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)) + typeStruct = (TypeTupleForm) 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 { - 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) + + /* + * 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); + relationStruct = (Form_pg_class) GETSTRUCT(relationTuple); + td = CreateTemplateTupleDesc(relationStruct->relnatts); } - else - td = CreateTemplateTupleDesc(1); - - ((TupleTableSlot*)retval->funcSlot)->ttc_tupleDescriptor = td; + else + td = CreateTemplateTupleDesc(1); + + ((TupleTableSlot *) retval->funcSlot)->ttc_tupleDescriptor = td; } - else - retval->funcSlot = (char *)NULL; - - nargs = procedureStruct->pronargs; - retval->nargs = nargs; - - if (nargs > 0) + 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) + 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)) + 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); + oneArg = lfirst(argList); + if (FuncArgTypeIsDynamic(oneArg)) + retval->argOidVect[i] = GetDynamicFuncArgType((Var *) oneArg, + econtext); } } - else - retval->argOidVect = (Oid *)NULL; + else + retval->argOidVect = (Oid *) NULL; } - else + else { - retval->argOidVect = (Oid *)NULL; - retval->nullVect = (BoolPtr)NULL; + 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) + + /* + * 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; + retval->src = textout(&(procedureStruct->prosrc)); + retval->bin = (char *) NULL; } - else + 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; + + /* + * 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)); - else - retval->func = (func_ptr)NULL; - - - return(retval); + + + + + if (retval->language != SQLlanguageId) + fmgr_info(foid, &(retval->func), &(retval->nargs)); + else + retval->func = (func_ptr) NULL; + + + return (retval); } void -setFcache(Node *node, Oid foid, List *argList, ExprContext *econtext) +setFcache(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(WARN, "init_fcache: node must be Oper or Func!"); - } + 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(WARN, "init_fcache: node must be Oper or Func!"); + } } |