parse_func.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:39k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * parse_func.c
  4.  * handle function calls in parser
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.47 1999/06/17 22:21:40 tgl Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <string.h>
  15. #include "postgres.h"
  16. #include "access/genam.h"
  17. #include "access/heapam.h"
  18. #include "access/itup.h"
  19. #include "access/relscan.h"
  20. #include "access/sdir.h"
  21. #include "catalog/catname.h"
  22. #include "catalog/heap.h"
  23. #include "catalog/indexing.h"
  24. #include "catalog/pg_inherits.h"
  25. #include "catalog/pg_proc.h"
  26. #include "catalog/pg_type.h"
  27. #include "catalog/pg_aggregate.h"
  28. #include "fmgr.h"
  29. #include "lib/dllist.h"
  30. #include "miscadmin.h"
  31. #include "nodes/makefuncs.h"
  32. #include "nodes/relation.h"
  33. #include "parser/parse_agg.h"
  34. #include "parser/parse_expr.h"
  35. #include "parser/parse_func.h"
  36. #include "parser/parse_node.h"
  37. #include "parser/parse_relation.h"
  38. #include "parser/parse_target.h"
  39. #include "parser/parse_type.h"
  40. #include "parser/parse_coerce.h"
  41. #include "storage/bufmgr.h"
  42. #include "storage/lmgr.h"
  43. #include "utils/acl.h"
  44. #include "utils/builtins.h"
  45. #include "utils/lsyscache.h"
  46. #include "utils/syscache.h"
  47. static Node *ParseComplexProjection(ParseState *pstate,
  48.    char *funcname,
  49.    Node *first_arg,
  50.    bool *attisset);
  51. static Oid **argtype_inherit(int nargs, Oid *oid_array);
  52. static int find_inheritors(Oid relid, Oid **supervec);
  53. static CandidateList func_get_candidates(char *funcname, int nargs);
  54. static bool
  55. func_get_detail(char *funcname,
  56. int nargs,
  57. Oid *oid_array,
  58. Oid *funcid, /* return value */
  59. Oid *rettype, /* return value */
  60. bool *retset, /* return value */
  61. Oid **true_typeids);
  62. static Oid funcid_get_rettype(Oid funcid);
  63. static Oid **gen_cross_product(InhPaths *arginh, int nargs);
  64. static void make_arguments(ParseState *pstate,
  65.    int nargs,
  66.    List *fargs,
  67.    Oid *input_typeids,
  68.    Oid *function_typeids);
  69. static int match_argtypes(int nargs,
  70.    Oid *input_typeids,
  71.    CandidateList function_typeids,
  72.    CandidateList *candidates);
  73. static List *setup_tlist(char *attname, Oid relid);
  74. static List *setup_base_tlist(Oid typeid);
  75. static Oid *func_select_candidate(int nargs, Oid *input_typeids,
  76.   CandidateList candidates);
  77. static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
  78. static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
  79. #define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
  80. typedef struct _SuperQE
  81. {
  82. Oid sqe_relid;
  83. } SuperQE;
  84. /*
  85.  ** ParseNestedFuncOrColumn
  86.  **    Given a nested dot expression (i.e. (relation func ... attr), build up
  87.  ** a tree with of Iter and Func nodes.
  88.  */
  89. Node *
  90. ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int *curr_resno, int precedence)
  91. {
  92. List    *mutator_iter;
  93. Node    *retval = NULL;
  94. if (attr->paramNo != NULL)
  95. {
  96. Param    *param = (Param *) transformExpr(pstate, (Node *) attr->paramNo, EXPR_RELATION_FIRST);
  97. retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)),
  98.    lcons(param, NIL),
  99.    curr_resno,
  100.    precedence);
  101. }
  102. else
  103. {
  104. Ident    *ident = makeNode(Ident);
  105. ident->name = attr->relname;
  106. ident->isRel = TRUE;
  107. retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)),
  108.    lcons(ident, NIL),
  109.    curr_resno,
  110.    precedence);
  111. }
  112. /* Do more attributes follow this one? */
  113. foreach(mutator_iter, lnext(attr->attrs))
  114. {
  115. retval = ParseFuncOrColumn(pstate, strVal(lfirst(mutator_iter)),
  116.    lcons(retval, NIL),
  117.    curr_resno,
  118.    precedence);
  119. }
  120. return retval;
  121. }
  122. static int
  123. agg_get_candidates(char *aggname,
  124.    Oid typeId,
  125.    CandidateList *candidates)
  126. {
  127. CandidateList current_candidate;
  128. Relation pg_aggregate_desc;
  129. HeapScanDesc pg_aggregate_scan;
  130. HeapTuple tup;
  131. Form_pg_aggregate agg;
  132. int ncandidates = 0;
  133. static ScanKeyData aggKey[1] = {
  134. {0, Anum_pg_aggregate_aggname, F_NAMEEQ}};
  135. *candidates = NULL;
  136. fmgr_info(F_NAMEEQ, (FmgrInfo *) &aggKey[0].sk_func);
  137. aggKey[0].sk_argument = NameGetDatum(aggname);
  138. pg_aggregate_desc = heap_openr(AggregateRelationName);
  139. pg_aggregate_scan = heap_beginscan(pg_aggregate_desc,
  140.    0,
  141.    SnapshotSelf, /* ??? */
  142.    1,
  143.    aggKey);
  144. while (HeapTupleIsValid(tup = heap_getnext(pg_aggregate_scan, 0)))
  145. {
  146. current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
  147. current_candidate->args = (Oid *) palloc(sizeof(Oid));
  148. agg = (Form_pg_aggregate) GETSTRUCT(tup);
  149. current_candidate->args[0] = agg->aggbasetype;
  150. current_candidate->next = *candidates;
  151. *candidates = current_candidate;
  152. ncandidates++;
  153. }
  154. heap_endscan(pg_aggregate_scan);
  155. heap_close(pg_aggregate_desc);
  156. return ncandidates;
  157. } /* agg_get_candidates() */
  158. /* agg_select_candidate()
  159.  * Try to choose only one candidate aggregate function from a list of possibles.
  160.  */
  161. static Oid
  162. agg_select_candidate(Oid typeid, CandidateList candidates)
  163. {
  164. CandidateList current_candidate;
  165. CandidateList last_candidate;
  166. Oid current_typeid;
  167. int ncandidates;
  168. CATEGORY category,
  169. current_category;
  170. /*
  171.  * Look for candidates which allow coersion and have a preferred type.
  172.  * Keep all candidates if none match.
  173.  */
  174. category = TypeCategory(typeid);
  175. ncandidates = 0;
  176. last_candidate = NULL;
  177. for (current_candidate = candidates;
  178.  current_candidate != NULL;
  179.  current_candidate = current_candidate->next)
  180. {
  181. current_typeid = current_candidate->args[0];
  182. current_category = TypeCategory(current_typeid);
  183. if ((current_category == category)
  184. && IsPreferredType(current_category, current_typeid)
  185. && can_coerce_type(1, &typeid, &current_typeid))
  186. {
  187. /* only one so far? then keep it... */
  188. if (last_candidate == NULL)
  189. {
  190. candidates = current_candidate;
  191. last_candidate = current_candidate;
  192. ncandidates = 1;
  193. }
  194. /* otherwise, keep this one too... */
  195. else
  196. {
  197. last_candidate->next = current_candidate;
  198. last_candidate = current_candidate;
  199. ncandidates++;
  200. }
  201. }
  202. /* otherwise, don't bother keeping this one around... */
  203. else if (last_candidate != NULL)
  204. last_candidate->next = NULL;
  205. }
  206. return ((ncandidates == 1) ? candidates->args[0] : 0);
  207. } /* agg_select_candidate() */
  208. /*
  209.  * parse function
  210.  */
  211. Node *
  212. ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
  213.   int *curr_resno, int precedence)
  214. {
  215. Oid rettype = InvalidOid;
  216. Oid argrelid = InvalidOid;
  217. Oid funcid = InvalidOid;
  218. List    *i = NIL;
  219. Node    *first_arg = NULL;
  220. char    *relname = NULL;
  221. char    *refname = NULL;
  222. Relation rd;
  223. Oid relid;
  224. int nargs;
  225. Func    *funcnode;
  226. Oid oid_array[MAXFARGS];
  227. Oid    *true_oid_array;
  228. Node    *retval;
  229. bool retset;
  230. bool attisset = false;
  231. Oid toid = InvalidOid;
  232. Expr    *expr;
  233. if (fargs)
  234. {
  235. first_arg = lfirst(fargs);
  236. if (first_arg == NULL)
  237. elog(ERROR, "Function '%s' does not allow NULL input", funcname);
  238. }
  239. /*
  240.  * check for projection methods: if function takes one argument, and
  241.  * that argument is a relation, param, or PQ function returning a
  242.  * complex * type, then the function could be a projection.
  243.  */
  244. /* We only have one parameter */
  245. if (length(fargs) == 1)
  246. {
  247. /* Is is a plain Relation name from the parser? */
  248. if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel)
  249. {
  250. RangeTblEntry *rte;
  251. Ident    *ident = (Ident *) first_arg;
  252. /*
  253.  * first arg is a relation. This could be a projection.
  254.  */
  255. refname = ident->name;
  256. rte = refnameRangeTableEntry(pstate, refname);
  257. if (rte == NULL)
  258. rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
  259. relname = rte->relname;
  260. relid = rte->relid;
  261. /*
  262.  * If the attr isn't a set, just make a var for it.  If it is
  263.  * a set, treat it like a function and drop through.
  264.  */
  265. if (get_attnum(relid, funcname) != InvalidAttrNumber)
  266. {
  267. return (Node *) make_var(pstate,
  268.  relid,
  269.  refname,
  270.  funcname);
  271. }
  272. else
  273. {
  274. /* drop through - attr is a set */
  275. ;
  276. }
  277. }
  278. else if (ISCOMPLEX(exprType(first_arg)))
  279. {
  280. /*
  281.  * Attempt to handle projection of a complex argument. If
  282.  * ParseComplexProjection can't handle the projection, we have
  283.  * to keep going.
  284.  */
  285. retval = ParseComplexProjection(pstate,
  286. funcname,
  287. first_arg,
  288. &attisset);
  289. if (attisset)
  290. {
  291. toid = exprType(first_arg);
  292. rd = heap_openr(typeidTypeName(toid));
  293. if (RelationIsValid(rd))
  294. {
  295. relname = RelationGetRelationName(rd)->data;
  296. heap_close(rd);
  297. }
  298. else
  299. elog(ERROR, "Type '%s' is not a relation type",
  300.  typeidTypeName(toid));
  301. argrelid = typeidTypeRelid(toid);
  302. /*
  303.  * A projection contains either an attribute name or the
  304.  * "*".
  305.  */
  306. if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
  307. && strcmp(funcname, "*"))
  308. elog(ERROR, "Functions on sets are not yet supported");
  309. }
  310. if (retval)
  311. return retval;
  312. }
  313. else
  314. {
  315. /*
  316.  * Parsing aggregates.
  317.  */
  318. Type tp;
  319. Oid basetype;
  320. int ncandidates;
  321. CandidateList candidates;
  322. /*
  323.  * the aggregate COUNT is a special case, ignore its base
  324.  * type.  Treat it as zero
  325.  */
  326. if (strcmp(funcname, "count") == 0)
  327. basetype = 0;
  328. else
  329. basetype = exprType(lfirst(fargs));
  330. /* try for exact match first... */
  331. if (SearchSysCacheTuple(AGGNAME,
  332. PointerGetDatum(funcname),
  333. ObjectIdGetDatum(basetype),
  334. 0, 0))
  335. return (Node *) ParseAgg(pstate, funcname, basetype,
  336.  fargs, precedence);
  337. /*
  338.  * No exact match yet, so see if there is another entry in the
  339.  * aggregate table which is compatible. - thomas 1998-12-05
  340.  */
  341. ncandidates = agg_get_candidates(funcname, basetype, &candidates);
  342. if (ncandidates > 0)
  343. {
  344. Oid type;
  345. type = agg_select_candidate(basetype, candidates);
  346. if (OidIsValid(type))
  347. {
  348. lfirst(fargs) = coerce_type(pstate, lfirst(fargs),
  349. basetype, type, -1);
  350. basetype = type;
  351. return (Node *) ParseAgg(pstate, funcname, basetype,
  352.  fargs, precedence);
  353. }
  354. else
  355. {
  356. elog(ERROR, "Unable to select an aggregate function %s(%s)",
  357.  funcname, typeidTypeName(basetype));
  358. }
  359. }
  360. /*
  361.  * See if this is a single argument function with the function
  362.  * name also a type name and the input argument and type name
  363.  * binary compatible... This means that you are trying for a
  364.  * type conversion which does not need to take place, so we'll
  365.  * just pass through the argument itself. (make this clearer
  366.  * with some extra brackets - thomas 1998-12-05)
  367.  */
  368. if ((HeapTupleIsValid(tp = SearchSysCacheTuple(TYPNAME,
  369.    PointerGetDatum(funcname),
  370.    0, 0, 0)))
  371. && IS_BINARY_COMPATIBLE(typeTypeId(tp), basetype))
  372. return ((Node *) lfirst(fargs));
  373. }
  374. }
  375. /*
  376.  * If we dropped through to here it's really a function (or a set,
  377.  * which is implemented as a function). Extract arg type info and
  378.  * transform relation name arguments into varnodes of the appropriate
  379.  * form.
  380.  */
  381. MemSet(oid_array, 0, MAXFARGS * sizeof(Oid));
  382. nargs = 0;
  383. foreach(i, fargs)
  384. {
  385. int vnum;
  386. RangeTblEntry *rte;
  387. Node    *pair = lfirst(i);
  388. if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
  389. {
  390. /*
  391.  * a relation
  392.  */
  393. refname = ((Ident *) pair)->name;
  394. rte = refnameRangeTableEntry(pstate, refname);
  395. if (rte == NULL)
  396. rte = addRangeTableEntry(pstate, refname, refname,
  397.  FALSE, FALSE);
  398. relname = rte->relname;
  399. vnum = refnameRangeTablePosn(pstate, rte->refname, NULL);
  400. /*
  401.  * for func(relname), the param to the function is the tuple
  402.  * under consideration.  we build a special VarNode to reflect
  403.  * this -- it has varno set to the correct range table entry,
  404.  * but has varattno == 0 to signal that the whole tuple is the
  405.  * argument.
  406.  */
  407. toid = typeTypeId(typenameType(relname));
  408. /* replace it in the arg list */
  409. lfirst(fargs) = makeVar(vnum, 0, toid, -1, 0, vnum, 0);
  410. }
  411. else if (!attisset)
  412. { /* set functions don't have parameters */
  413. /*
  414.  * any functiona args which are typed "unknown", but aren't
  415.  * constants, we don't know what to do with, because we can't
  416.  * cast them - jolly
  417.  */
  418. if (exprType(pair) == UNKNOWNOID && !IsA(pair, Const))
  419. elog(ERROR, "There is no function '%s'"
  420.  " with argument #%d of type UNKNOWN",
  421.  funcname, nargs);
  422. else
  423. toid = exprType(pair);
  424. }
  425. /* Most of the rest of the parser just assumes that functions do not
  426.  * have more than MAXFARGS parameters.  We have to test here to protect
  427.  * against array overruns, etc.
  428.  */
  429. if (nargs >= MAXFARGS)
  430. elog(ERROR, "Cannot pass more than %d arguments to a function",
  431.  MAXFARGS);
  432. oid_array[nargs++] = toid;
  433. }
  434. /*
  435.  * func_get_detail looks up the function in the catalogs, does
  436.  * disambiguation for polymorphic functions, handles inheritance, and
  437.  * returns the funcid and type and set or singleton status of the
  438.  * function's return value.  it also returns the true argument types
  439.  * to the function.  if func_get_detail returns true, the function
  440.  * exists. otherwise, there was an error.
  441.  */
  442. if (attisset)
  443. { /* we know all of these fields already */
  444. /*
  445.  * We create a funcnode with a placeholder function SetEval.
  446.  * SetEval() never actually gets executed. When the function
  447.  * evaluation routines see it, they use the funcid projected out
  448.  * from the relation as the actual function to call. Example:
  449.  * retrieve (emp.mgr.name) The plan for this will scan the emp
  450.  * relation, projecting out the mgr attribute, which is a funcid.
  451.  * This function is then called (instead of SetEval) and "name" is
  452.  * projected from its result.
  453.  */
  454. funcid = F_SETEVAL;
  455. rettype = toid;
  456. retset = true;
  457. true_oid_array = oid_array;
  458. }
  459. else
  460. {
  461. bool exists;
  462. exists = func_get_detail(funcname, nargs, oid_array, &funcid,
  463.  &rettype, &retset, &true_oid_array);
  464. if (!exists)
  465. elog(ERROR, "No such function '%s' with the specified attributes",
  466.  funcname);
  467. }
  468. /* got it */
  469. funcnode = makeNode(Func);
  470. funcnode->funcid = funcid;
  471. funcnode->functype = rettype;
  472. funcnode->funcisindex = false;
  473. funcnode->funcsize = 0;
  474. funcnode->func_fcache = NULL;
  475. funcnode->func_tlist = NIL;
  476. funcnode->func_planlist = NIL;
  477. /* perform the necessary typecasting */
  478. make_arguments(pstate, nargs, fargs, oid_array, true_oid_array);
  479. /*
  480.  * for functions returning base types, we want to project out the
  481.  * return value.  set up a target list to do that. the executor will
  482.  * ignore these for c functions, and do the right thing for postquel
  483.  * functions.
  484.  */
  485. if (typeidTypeRelid(rettype) == InvalidOid)
  486. funcnode->func_tlist = setup_base_tlist(rettype);
  487. /*
  488.  * For sets, we want to make a targetlist to project out this
  489.  * attribute of the set tuples.
  490.  */
  491. if (attisset)
  492. {
  493. if (!strcmp(funcname, "*"))
  494. funcnode->func_tlist = expandAll(pstate, relname, refname, curr_resno);
  495. else
  496. {
  497. funcnode->func_tlist = setup_tlist(funcname, argrelid);
  498. rettype = get_atttype(argrelid, get_attnum(argrelid, funcname));
  499. }
  500. }
  501. /*
  502.  * Sequence handling.
  503.  */
  504. if (funcid == F_NEXTVAL ||
  505. funcid == F_CURRVAL ||
  506. funcid == F_SETVAL)
  507. {
  508. Const    *seq;
  509. char    *seqrel;
  510. text    *seqname;
  511. int32 aclcheck_result = -1;
  512. Assert(length(fargs) == ((funcid == F_SETVAL) ? 2 : 1));
  513. seq = (Const *) lfirst(fargs);
  514. if (!IsA((Node *) seq, Const))
  515. elog(ERROR, "Only constant sequence names are acceptable for function '%s'", funcname);
  516. seqrel = textout((text *) DatumGetPointer(seq->constvalue));
  517. /* Do we have nextval('"Aa"')? */
  518. if (strlen(seqrel) >= 2 &&
  519. seqrel[0] == '"' && seqrel[strlen(seqrel) - 1] == '"')
  520. {
  521. /* strip off quotes, keep case */
  522. seqrel = pstrdup(seqrel + 1);
  523. seqrel[strlen(seqrel) - 1] = '';
  524. pfree(DatumGetPointer(seq->constvalue));
  525. seq->constvalue = (Datum) textin(seqrel);
  526. }
  527. else
  528. {
  529. pfree(seqrel);
  530. seqname = lower((text *) DatumGetPointer(seq->constvalue));
  531. pfree(DatumGetPointer(seq->constvalue));
  532. seq->constvalue = PointerGetDatum(seqname);
  533. seqrel = textout(seqname);
  534. }
  535. if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
  536.    (((funcid == F_NEXTVAL) || (funcid == F_SETVAL)) ?
  537. ACL_WR : ACL_RD)))
  538. != ACLCHECK_OK)
  539. elog(ERROR, "%s.%s: %s",
  540.   seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
  541. pfree(seqrel);
  542. if (funcid == F_NEXTVAL && pstate->p_in_where_clause)
  543. elog(ERROR, "Sequence function nextval is not allowed in WHERE clauses");
  544. if (funcid == F_SETVAL && pstate->p_in_where_clause)
  545. elog(ERROR, "Sequence function setval is not allowed in WHERE clauses");
  546. }
  547. expr = makeNode(Expr);
  548. expr->typeOid = rettype;
  549. expr->opType = FUNC_EXPR;
  550. expr->oper = (Node *) funcnode;
  551. expr->args = fargs;
  552. retval = (Node *) expr;
  553. /*
  554.  * if the function returns a set of values, then we need to iterate
  555.  * over all the returned values in the executor, so we stick an iter
  556.  * node here.  if it returns a singleton, then we don't need the iter
  557.  * node.
  558.  */
  559. if (retset)
  560. {
  561. Iter    *iter = makeNode(Iter);
  562. iter->itertype = rettype;
  563. iter->iterexpr = retval;
  564. retval = (Node *) iter;
  565. }
  566. return retval;
  567. }
  568. static Oid
  569. funcid_get_rettype(Oid funcid)
  570. {
  571. HeapTuple func_tuple = NULL;
  572. Oid funcrettype = InvalidOid;
  573. func_tuple = SearchSysCacheTuple(PROOID,
  574.  ObjectIdGetDatum(funcid),
  575.  0, 0, 0);
  576. if (!HeapTupleIsValid(func_tuple))
  577. elog(ERROR, "Function OID %u does not exist", funcid);
  578. funcrettype = (Oid)
  579. ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
  580. return funcrettype;
  581. }
  582. /* func_get_candidates()
  583.  * get a list of all argument type vectors for which a function named
  584.  * funcname taking nargs arguments exists
  585.  */
  586. static CandidateList
  587. func_get_candidates(char *funcname, int nargs)
  588. {
  589. Relation heapRelation;
  590. Relation idesc;
  591. ScanKeyData skey;
  592. HeapTupleData tuple;
  593. IndexScanDesc sd;
  594. RetrieveIndexResult indexRes;
  595. Form_pg_proc pgProcP;
  596. CandidateList candidates = NULL;
  597. CandidateList current_candidate;
  598. int i;
  599. heapRelation = heap_openr(ProcedureRelationName);
  600. ScanKeyEntryInitialize(&skey,
  601.    (bits16) 0x0,
  602.    (AttrNumber) 1,
  603.    (RegProcedure) F_NAMEEQ,
  604.    (Datum) funcname);
  605. idesc = index_openr(ProcedureNameIndex);
  606. sd = index_beginscan(idesc, false, 1, &skey);
  607. do
  608. {
  609. indexRes = index_getnext(sd, ForwardScanDirection);
  610. if (indexRes)
  611. {
  612. Buffer buffer;
  613. tuple.t_self = indexRes->heap_iptr;
  614. heap_fetch(heapRelation, SnapshotNow, &tuple, &buffer);
  615. pfree(indexRes);
  616. if (tuple.t_data != NULL)
  617. {
  618. pgProcP = (Form_pg_proc) GETSTRUCT(&tuple);
  619. if (pgProcP->pronargs == nargs)
  620. {
  621. current_candidate = (CandidateList)
  622. palloc(sizeof(struct _CandidateList));
  623. current_candidate->args = (Oid *)
  624. palloc(MAXFARGS * sizeof(Oid));
  625. MemSet(current_candidate->args, 0, MAXFARGS * sizeof(Oid));
  626. for (i = 0; i < nargs; i++)
  627. current_candidate->args[i] = pgProcP->proargtypes[i];
  628. current_candidate->next = candidates;
  629. candidates = current_candidate;
  630. }
  631. ReleaseBuffer(buffer);
  632. }
  633. }
  634. } while (indexRes);
  635. index_endscan(sd);
  636. index_close(idesc);
  637. heap_close(heapRelation);
  638. return candidates;
  639. }
  640. /* match_argtypes()
  641.  * Given a list of possible typeid arrays to a function and an array of
  642.  * input typeids, produce a shortlist of those function typeid arrays
  643.  * that match the input typeids (either exactly or by coercion), and
  644.  * return the number of such arrays
  645.  */
  646. static int
  647. match_argtypes(int nargs,
  648.    Oid *input_typeids,
  649.    CandidateList function_typeids,
  650.    CandidateList *candidates) /* return value */
  651. {
  652. CandidateList current_candidate;
  653. CandidateList matching_candidate;
  654. Oid    *current_typeids;
  655. int ncandidates = 0;
  656. *candidates = NULL;
  657. for (current_candidate = function_typeids;
  658.  current_candidate != NULL;
  659.  current_candidate = current_candidate->next)
  660. {
  661. current_typeids = current_candidate->args;
  662. if (can_coerce_type(nargs, input_typeids, current_typeids))
  663. {
  664. matching_candidate = (CandidateList)
  665. palloc(sizeof(struct _CandidateList));
  666. matching_candidate->args = current_typeids;
  667. matching_candidate->next = *candidates;
  668. *candidates = matching_candidate;
  669. ncandidates++;
  670. }
  671. }
  672. return ncandidates;
  673. } /* match_argtypes() */
  674. /* func_select_candidate()
  675.  * Given the input argtype array and more than one candidate
  676.  * for the function argtype array, attempt to resolve the conflict.
  677.  * returns the selected argtype array if the conflict can be resolved,
  678.  * otherwise returns NULL.
  679.  *
  680.  * If all input Oids are UNKNOWNOID, then try matching with TEXTOID.
  681.  * Otherwise, could return first function arguments on list of candidates.
  682.  * But for now, return NULL and make the user give a better hint.
  683.  * - thomas 1998-03-17
  684.  */
  685. static Oid *
  686. func_select_candidate(int nargs,
  687.   Oid *input_typeids,
  688.   CandidateList candidates)
  689. {
  690. CandidateList current_candidate;
  691. CandidateList last_candidate;
  692. Oid    *current_typeids;
  693. int i;
  694. int ncandidates;
  695. int nbestMatch,
  696. nmatch,
  697. nident;
  698. CATEGORY slot_category,
  699. current_category;
  700. Oid slot_type,
  701. current_type;
  702. /*
  703.  * Run through all candidates and keep those with the most matches
  704.  * on explicit types. Keep all candidates if none match.
  705.  */
  706. ncandidates = 0;
  707. nbestMatch = 0;
  708. last_candidate = NULL;
  709. for (current_candidate = candidates;
  710.  current_candidate != NULL;
  711.  current_candidate = current_candidate->next)
  712. {
  713. current_typeids = current_candidate->args;
  714. nmatch = 0;
  715. nident = 0;
  716. for (i = 0; i < nargs; i++)
  717. {
  718. if ((input_typeids[i] != UNKNOWNOID)
  719. && (current_typeids[i] == input_typeids[i]))
  720. nmatch++;
  721. else if (IS_BINARY_COMPATIBLE(current_typeids[i], input_typeids[i]))
  722. nident++;
  723. }
  724. if ((nmatch + nident) == nargs)
  725. return current_candidate->args;
  726. if ((nmatch > nbestMatch) || (last_candidate == NULL))
  727. {
  728. nbestMatch = nmatch;
  729. candidates = current_candidate;
  730. last_candidate = current_candidate;
  731. ncandidates = 1;
  732. }
  733. else if (nmatch == nbestMatch)
  734. {
  735. last_candidate->next = current_candidate;
  736. last_candidate = current_candidate;
  737. ncandidates++;
  738. }
  739. else
  740. last_candidate->next = NULL;
  741. }
  742. if (ncandidates == 1)
  743. return candidates->args;
  744. /*
  745.  * Still too many candidates?
  746.  * Try assigning types for the unknown columns.
  747.  */
  748. for (i = 0; i < nargs; i++)
  749. {
  750. if (input_typeids[i] == UNKNOWNOID)
  751. {
  752. slot_category = INVALID_TYPE;
  753. slot_type = InvalidOid;
  754. for (current_candidate = candidates;
  755.  current_candidate != NULL;
  756.  current_candidate = current_candidate->next)
  757. {
  758. current_typeids = current_candidate->args;
  759. current_type = current_typeids[i];
  760. current_category = TypeCategory(current_typeids[i]);
  761. if (slot_category == InvalidOid)
  762. {
  763. slot_category = current_category;
  764. slot_type = current_type;
  765. }
  766. else if ((current_category != slot_category)
  767.  && IS_BUILTIN_TYPE(current_type))
  768. return NULL;
  769. else if (current_type != slot_type)
  770. {
  771. if (IsPreferredType(slot_category, current_type))
  772. {
  773. slot_type = current_type;
  774. candidates = current_candidate;
  775. }
  776. else if (IsPreferredType(slot_category, slot_type))
  777. candidates->next = current_candidate->next;
  778. }
  779. }
  780. if (slot_type != InvalidOid)
  781. input_typeids[i] = slot_type;
  782. }
  783. else
  784. {
  785. }
  786. }
  787. ncandidates = 0;
  788. for (current_candidate = candidates;
  789.  current_candidate != NULL;
  790.  current_candidate = current_candidate->next)
  791. ncandidates++;
  792. if (ncandidates == 1)
  793. return candidates->args;
  794. return NULL;
  795. } /* func_select_candidate() */
  796. /* func_get_detail()
  797.  * Find the named function in the system catalogs.
  798.  *
  799.  * Attempt to find the named function in the system catalogs with
  800.  * arguments exactly as specified, so that the normal case
  801.  * (exact match) is as quick as possible.
  802.  *
  803.  * If an exact match isn't found:
  804.  * 1) get a vector of all possible input arg type arrays constructed
  805.  *    from the superclasses of the original input arg types
  806.  * 2) get a list of all possible argument type arrays to the function
  807.  *    with given name and number of arguments
  808.  * 3) for each input arg type array from vector #1:
  809.  *  a) find how many of the function arg type arrays from list #2
  810.  * it can be coerced to
  811.  *  b) if the answer is one, we have our function
  812.  *  c) if the answer is more than one, attempt to resolve the conflict
  813.  *  d) if the answer is zero, try the next array from vector #1
  814.  */
  815. static bool
  816. func_get_detail(char *funcname,
  817. int nargs,
  818. Oid *oid_array,
  819. Oid *funcid, /* return value */
  820. Oid *rettype, /* return value */
  821. bool *retset, /* return value */
  822. Oid **true_typeids) /* return value */
  823. {
  824. Oid   **input_typeid_vector;
  825. Oid    *current_input_typeids;
  826. CandidateList function_typeids;
  827. CandidateList current_function_typeids;
  828. HeapTuple ftup;
  829. Form_pg_proc pform;
  830. /* attempt to find with arguments exactly as specified... */
  831. ftup = SearchSysCacheTuple(PRONAME,
  832.    PointerGetDatum(funcname),
  833.    Int32GetDatum(nargs),
  834.    PointerGetDatum(oid_array),
  835.    0);
  836. *true_typeids = oid_array;
  837. /* didn't find an exact match, so now try to match up candidates... */
  838. if (!HeapTupleIsValid(ftup))
  839. {
  840. function_typeids = func_get_candidates(funcname, nargs);
  841. /* found something, so let's look through them... */
  842. if (function_typeids != NULL)
  843. {
  844. int ncandidates;
  845. input_typeid_vector = argtype_inherit(nargs, oid_array);
  846. current_input_typeids = oid_array;
  847. do
  848. {
  849. ncandidates = match_argtypes(nargs, current_input_typeids,
  850.  function_typeids,
  851.  &current_function_typeids);
  852. /* one match only? then run with it... */
  853. if (ncandidates == 1)
  854. {
  855. *true_typeids = current_function_typeids->args;
  856. ftup = SearchSysCacheTuple(PRONAME,
  857.    PointerGetDatum(funcname),
  858.    Int32GetDatum(nargs),
  859.   PointerGetDatum(*true_typeids),
  860.    0);
  861. Assert(HeapTupleIsValid(ftup));
  862. }
  863. /*
  864.  * multiple candidates? then better decide or throw an
  865.  * error...
  866.  */
  867. else if (ncandidates > 1)
  868. {
  869. *true_typeids = func_select_candidate(nargs,
  870.    current_input_typeids,
  871.    current_function_typeids);
  872. /* couldn't decide, so quit */
  873. if (*true_typeids == NULL)
  874. {
  875. func_error(NULL, funcname, nargs, oid_array,
  876.    "Unable to identify a function which satisfies the given argument types"
  877.    "ntYou will have to retype your query using explicit typecasts");
  878. }
  879. /* found something, so use the first one... */
  880. else
  881. {
  882. ftup = SearchSysCacheTuple(PRONAME,
  883.    PointerGetDatum(funcname),
  884.    Int32GetDatum(nargs),
  885.   PointerGetDatum(*true_typeids),
  886.    0);
  887. Assert(HeapTupleIsValid(ftup));
  888. }
  889. }
  890. current_input_typeids = *input_typeid_vector++;
  891. }
  892. while (current_input_typeids != InvalidOid && ncandidates == 0);
  893. }
  894. }
  895. if (!HeapTupleIsValid(ftup))
  896. {
  897. Type tp;
  898. if (nargs == 1)
  899. {
  900. tp = typeidType(oid_array[0]);
  901. if (typeTypeFlag(tp) == 'c')
  902. elog(ERROR, "No such attribute or function '%s'", funcname);
  903. }
  904. }
  905. else
  906. {
  907. pform = (Form_pg_proc) GETSTRUCT(ftup);
  908. *funcid = ftup->t_data->t_oid;
  909. *rettype = pform->prorettype;
  910. *retset = pform->proretset;
  911. return true;
  912. }
  913. /* shouldn't reach here */
  914. return false;
  915. } /* func_get_detail() */
  916. /*
  917.  * argtype_inherit() -- Construct an argtype vector reflecting the
  918.  *  inheritance properties of the supplied argv.
  919.  *
  920.  * This function is used to disambiguate among functions with the
  921.  * same name but different signatures.  It takes an array of eight
  922.  * type ids.  For each type id in the array that's a complex type
  923.  * (a class), it walks up the inheritance tree, finding all
  924.  * superclasses of that type. A vector of new Oid type arrays
  925.  * is returned to the caller, reflecting the structure of the
  926.  * inheritance tree above the supplied arguments.
  927.  *
  928.  * The order of this vector is as follows:  all superclasses of the
  929.  * rightmost complex class are explored first.  The exploration
  930.  * continues from right to left.  This policy means that we favor
  931.  * keeping the leftmost argument type as low in the inheritance tree
  932.  * as possible.  This is intentional; it is exactly what we need to
  933.  * do for method dispatch.  The last type array we return is all
  934.  * zeroes.  This will match any functions for which return types are
  935.  * not defined.  There are lots of these (mostly builtins) in the
  936.  * catalogs.
  937.  */
  938. static Oid **
  939. argtype_inherit(int nargs, Oid *oid_array)
  940. {
  941. Oid relid;
  942. int i;
  943. InhPaths arginh[MAXFARGS];
  944. for (i = 0; i < MAXFARGS; i++)
  945. {
  946. if (i < nargs)
  947. {
  948. arginh[i].self = oid_array[i];
  949. if ((relid = typeidTypeRelid(oid_array[i])) != InvalidOid)
  950. arginh[i].nsupers = find_inheritors(relid, &(arginh[i].supervec));
  951. else
  952. {
  953. arginh[i].nsupers = 0;
  954. arginh[i].supervec = (Oid *) NULL;
  955. }
  956. }
  957. else
  958. {
  959. arginh[i].self = InvalidOid;
  960. arginh[i].nsupers = 0;
  961. arginh[i].supervec = (Oid *) NULL;
  962. }
  963. }
  964. /* return an ordered cross-product of the classes involved */
  965. return gen_cross_product(arginh, nargs);
  966. }
  967. static int
  968. find_inheritors(Oid relid, Oid **supervec)
  969. {
  970. Oid    *relidvec;
  971. Relation inhrel;
  972. HeapScanDesc inhscan;
  973. ScanKeyData skey;
  974. HeapTuple inhtup;
  975. TupleDesc inhtupdesc;
  976. int nvisited;
  977. SuperQE    *qentry,
  978.    *vnode;
  979. Dllist    *visited,
  980.    *queue;
  981. Dlelem    *qe,
  982.    *elt;
  983. Relation rd;
  984. Datum d;
  985. bool newrelid;
  986. char isNull;
  987. nvisited = 0;
  988. queue = DLNewList();
  989. visited = DLNewList();
  990. inhrel = heap_openr(InheritsRelationName);
  991. inhtupdesc = RelationGetDescr(inhrel);
  992. /*
  993.  * Use queue to do a breadth-first traversal of the inheritance graph
  994.  * from the relid supplied up to the root.
  995.  */
  996. do
  997. {
  998. ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
  999.    F_OIDEQ,
  1000.    ObjectIdGetDatum(relid));
  1001. inhscan = heap_beginscan(inhrel, 0, SnapshotNow, 1, &skey);
  1002. while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0)))
  1003. {
  1004. qentry = (SuperQE *) palloc(sizeof(SuperQE));
  1005. d = fastgetattr(inhtup, Anum_pg_inherits_inhparent,
  1006. inhtupdesc, &isNull);
  1007. qentry->sqe_relid = DatumGetObjectId(d);
  1008. /* put this one on the queue */
  1009. DLAddTail(queue, DLNewElem(qentry));
  1010. }
  1011. heap_endscan(inhscan);
  1012. /* pull next unvisited relid off the queue */
  1013. do
  1014. {
  1015. qe = DLRemHead(queue);
  1016. qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL;
  1017. if (qentry == (SuperQE *) NULL)
  1018. break;
  1019. relid = qentry->sqe_relid;
  1020. newrelid = true;
  1021. for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
  1022. {
  1023. vnode = (SuperQE *) DLE_VAL(elt);
  1024. if (vnode && (qentry->sqe_relid == vnode->sqe_relid))
  1025. {
  1026. newrelid = false;
  1027. break;
  1028. }
  1029. }
  1030. } while (!newrelid);
  1031. if (qentry != (SuperQE *) NULL)
  1032. {
  1033. /* save the type id, rather than the relation id */
  1034. if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
  1035. elog(ERROR, "Relid %u does not exist", qentry->sqe_relid);
  1036. qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data));
  1037. heap_close(rd);
  1038. DLAddTail(visited, qe);
  1039. nvisited++;
  1040. }
  1041. } while (qentry != (SuperQE *) NULL);
  1042. heap_close(inhrel);
  1043. if (nvisited > 0)
  1044. {
  1045. relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
  1046. *supervec = relidvec;
  1047. for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
  1048. {
  1049. vnode = (SuperQE *) DLE_VAL(elt);
  1050. *relidvec++ = vnode->sqe_relid;
  1051. }
  1052. }
  1053. else
  1054. *supervec = (Oid *) NULL;
  1055. return nvisited;
  1056. }
  1057. static Oid **
  1058. gen_cross_product(InhPaths *arginh, int nargs)
  1059. {
  1060. int nanswers;
  1061. Oid   **result,
  1062.   **iter;
  1063. Oid    *oneres;
  1064. int i,
  1065. j;
  1066. int cur[MAXFARGS];
  1067. nanswers = 1;
  1068. for (i = 0; i < nargs; i++)
  1069. {
  1070. nanswers *= (arginh[i].nsupers + 2);
  1071. cur[i] = 0;
  1072. }
  1073. iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
  1074. /* compute the cross product from right to left */
  1075. for (;;)
  1076. {
  1077. oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
  1078. MemSet(oneres, 0, MAXFARGS * sizeof(Oid));
  1079. for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
  1080. continue;
  1081. /* if we're done, terminate with NULL pointer */
  1082. if (i < 0)
  1083. {
  1084. *iter = NULL;
  1085. return result;
  1086. }
  1087. /* no, increment this column and zero the ones after it */
  1088. cur[i] = cur[i] + 1;
  1089. for (j = nargs - 1; j > i; j--)
  1090. cur[j] = 0;
  1091. for (i = 0; i < nargs; i++)
  1092. {
  1093. if (cur[i] == 0)
  1094. oneres[i] = arginh[i].self;
  1095. else if (cur[i] > arginh[i].nsupers)
  1096. oneres[i] = 0; /* wild card */
  1097. else
  1098. oneres[i] = arginh[i].supervec[cur[i] - 1];
  1099. }
  1100. *iter++ = oneres;
  1101. }
  1102. }
  1103. /* make_arguments()
  1104.  * Given the number and types of arguments to a function, and the
  1105.  * actual arguments and argument types, do the necessary typecasting.
  1106.  *
  1107.  * There are two ways an input typeid can differ from a function typeid:
  1108.  * 1) the input type inherits the function type, so no typecasting required
  1109.  * 2) the input type can be typecast into the function type
  1110.  * Right now, we only typecast unknowns, and that is all we check for.
  1111.  *
  1112.  * func_get_detail() now can find coersions for function arguments which
  1113.  * will make this function executable. So, we need to recover these
  1114.  * results here too.
  1115.  * - thomas 1998-03-25
  1116.  */
  1117. static void
  1118. make_arguments(ParseState *pstate,
  1119.    int nargs,
  1120.    List *fargs,
  1121.    Oid *input_typeids,
  1122.    Oid *function_typeids)
  1123. {
  1124. List    *current_fargs;
  1125. int i;
  1126. for (i = 0, current_fargs = fargs;
  1127.  i < nargs;
  1128.  i++, current_fargs = lnext(current_fargs))
  1129. {
  1130. /*
  1131.  * unspecified type for string constant? then use heuristics for
  1132.  * conversion...
  1133.  */
  1134. if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
  1135. {
  1136. lfirst(current_fargs) = parser_typecast2(lfirst(current_fargs),
  1137.  input_typeids[i],
  1138.  typeidType(function_typeids[i]),
  1139.  -1);
  1140. }
  1141. /* types don't match? then force coersion using a function call... */
  1142. else if (input_typeids[i] != function_typeids[i])
  1143. {
  1144. lfirst(current_fargs) = coerce_type(pstate,
  1145. lfirst(current_fargs),
  1146. input_typeids[i],
  1147. function_typeids[i], -1);
  1148. }
  1149. }
  1150. }
  1151. /*
  1152.  ** setup_tlist
  1153.  ** Build a tlist that says which attribute to project to.
  1154.  ** This routine is called by ParseFuncOrColumn() to set up a target list
  1155.  ** on a tuple parameter or return value.  Due to a bug in 4.0,
  1156.  ** it's not possible to refer to system attributes in this case.
  1157.  */
  1158. static List *
  1159. setup_tlist(char *attname, Oid relid)
  1160. {
  1161. TargetEntry *tle;
  1162. Resdom    *resnode;
  1163. Var    *varnode;
  1164. Oid typeid;
  1165. int32 type_mod;
  1166. int attno;
  1167. attno = get_attnum(relid, attname);
  1168. if (attno < 0)
  1169. elog(ERROR, "Cannot reference attribute '%s'"
  1170.  " of tuple params/return values for functions", attname);
  1171. typeid = get_atttype(relid, attno);
  1172. type_mod = get_atttypmod(relid, attno);
  1173. resnode = makeResdom(1,
  1174.  typeid,
  1175.  type_mod,
  1176.  get_attname(relid, attno),
  1177.  0,
  1178.  InvalidOid,
  1179.  false);
  1180. varnode = makeVar(-1, attno, typeid, type_mod, 0, -1, attno);
  1181. tle = makeTargetEntry(resnode, (Node *) varnode);
  1182. return lcons(tle, NIL);
  1183. }
  1184. /*
  1185.  ** setup_base_tlist
  1186.  ** Build a tlist that extracts a base type from the tuple
  1187.  ** returned by the executor.
  1188.  */
  1189. static List *
  1190. setup_base_tlist(Oid typeid)
  1191. {
  1192. TargetEntry *tle;
  1193. Resdom    *resnode;
  1194. Var    *varnode;
  1195. resnode = makeResdom(1,
  1196.  typeid,
  1197.  -1,
  1198.  "<noname>",
  1199.  0,
  1200.  InvalidOid,
  1201.  false);
  1202. varnode = makeVar(-1, 1, typeid, -1, 0, -1, 1);
  1203. tle = makeTargetEntry(resnode, (Node *) varnode);
  1204. return lcons(tle, NIL);
  1205. }
  1206. /*
  1207.  * ParseComplexProjection -
  1208.  *   handles function calls with a single argument that is of complex type.
  1209.  *   This routine returns NULL if it can't handle the projection (eg. sets).
  1210.  */
  1211. static Node *
  1212. ParseComplexProjection(ParseState *pstate,
  1213.    char *funcname,
  1214.    Node *first_arg,
  1215.    bool *attisset)
  1216. {
  1217. Oid argtype;
  1218. Oid argrelid;
  1219. Relation rd;
  1220. Oid relid;
  1221. int attnum;
  1222. switch (nodeTag(first_arg))
  1223. {
  1224. case T_Iter:
  1225. {
  1226. Func    *func;
  1227. Iter    *iter;
  1228. iter = (Iter *) first_arg;
  1229. func = (Func *) ((Expr *) iter->iterexpr)->oper;
  1230. argtype = funcid_get_rettype(func->funcid);
  1231. argrelid = typeidTypeRelid(argtype);
  1232. if (argrelid &&
  1233. ((attnum = get_attnum(argrelid, funcname))
  1234.  != InvalidAttrNumber))
  1235. {
  1236. /*
  1237.  * the argument is a function returning a tuple, so
  1238.  * funcname may be a projection
  1239.  */
  1240. /* add a tlist to the func node and return the Iter */
  1241. rd = heap_openr(typeidTypeName(argtype));
  1242. if (RelationIsValid(rd))
  1243. {
  1244. relid = RelationGetRelid(rd);
  1245. heap_close(rd);
  1246. }
  1247. if (RelationIsValid(rd))
  1248. {
  1249. func->func_tlist = setup_tlist(funcname, argrelid);
  1250. iter->itertype = attnumTypeId(rd, attnum);
  1251. return (Node *) iter;
  1252. }
  1253. else
  1254. {
  1255. elog(ERROR, "Function '%s' has bad return type %d",
  1256.  funcname, argtype);
  1257. }
  1258. }
  1259. else
  1260. {
  1261. /* drop through */
  1262. ;
  1263. }
  1264. break;
  1265. }
  1266. case T_Var:
  1267. {
  1268. /*
  1269.  * The argument is a set, so this is either a projection
  1270.  * or a function call on this set.
  1271.  */
  1272. *attisset = true;
  1273. break;
  1274. }
  1275. case T_Expr:
  1276. {
  1277. Expr    *expr = (Expr *) first_arg;
  1278. Func    *funcnode;
  1279. if (expr->opType != FUNC_EXPR)
  1280. break;
  1281. funcnode = (Func *) expr->oper;
  1282. argtype = funcid_get_rettype(funcnode->funcid);
  1283. argrelid = typeidTypeRelid(argtype);
  1284. /*
  1285.  * the argument is a function returning a tuple, so
  1286.  * funcname may be a projection
  1287.  */
  1288. if (argrelid &&
  1289. (attnum = get_attnum(argrelid, funcname))
  1290. != InvalidAttrNumber)
  1291. {
  1292. /* add a tlist to the func node */
  1293. rd = heap_openr(typeidTypeName(argtype));
  1294. if (RelationIsValid(rd))
  1295. {
  1296. relid = RelationGetRelid(rd);
  1297. heap_close(rd);
  1298. }
  1299. if (RelationIsValid(rd))
  1300. {
  1301. Expr    *newexpr;
  1302. funcnode->func_tlist = setup_tlist(funcname, argrelid);
  1303. funcnode->functype = attnumTypeId(rd, attnum);
  1304. newexpr = makeNode(Expr);
  1305. newexpr->typeOid = funcnode->functype;
  1306. newexpr->opType = FUNC_EXPR;
  1307. newexpr->oper = (Node *) funcnode;
  1308. newexpr->args = expr->args;
  1309. return (Node *) newexpr;
  1310. }
  1311. }
  1312. break;
  1313. }
  1314. case T_Param:
  1315. {
  1316. Param    *param = (Param *) first_arg;
  1317. /*
  1318.  * If the Param is a complex type, this could be a
  1319.  * projection
  1320.  */
  1321. rd = heap_openr(typeidTypeName(param->paramtype));
  1322. if (RelationIsValid(rd))
  1323. {
  1324. relid = RelationGetRelid(rd);
  1325. heap_close(rd);
  1326. if ((attnum = get_attnum(relid, funcname))
  1327. != InvalidAttrNumber)
  1328. {
  1329. param->paramtype = attnumTypeId(rd, attnum);
  1330. param->param_tlist = setup_tlist(funcname, relid);
  1331. return (Node *) param;
  1332. }
  1333. }
  1334. break;
  1335. }
  1336. default:
  1337. break;
  1338. }
  1339. return NULL;
  1340. }
  1341. /*
  1342.  * Error message when function lookup fails that gives details of the
  1343.  * argument types
  1344.  */
  1345. void
  1346. func_error(char *caller, char *funcname, int nargs, Oid *argtypes, char *msg)
  1347. {
  1348. char p[(NAMEDATALEN + 2) * MAXFMGRARGS],
  1349.    *ptr;
  1350. int i;
  1351. ptr = p;
  1352. *ptr = '';
  1353. for (i = 0; i < nargs; i++)
  1354. {
  1355. if (i)
  1356. {
  1357. *ptr++ = ',';
  1358. *ptr++ = ' ';
  1359. }
  1360. if (argtypes[i] != 0)
  1361. {
  1362. strcpy(ptr, typeidTypeName(argtypes[i]));
  1363. *(ptr + NAMEDATALEN) = '';
  1364. }
  1365. else
  1366. strcpy(ptr, "opaque");
  1367. ptr += strlen(ptr);
  1368. }
  1369. if (caller == NULL)
  1370. {
  1371. elog(ERROR, "Function '%s(%s)' does not exist%s%s",
  1372.  funcname, p, ((msg != NULL) ? "nt" : ""), ((msg != NULL) ? msg : ""));
  1373. }
  1374. else
  1375. {
  1376. elog(ERROR, "%s: function '%s(%s)' does not exist%s%s",
  1377.  caller, funcname, p, ((msg != NULL) ? "nt" : ""), ((msg != NULL) ? msg : ""));
  1378. }
  1379. }