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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * execQual.c
  4.  *   Routines to evaluate qualification and targetlist expressions
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/execQual.c,v 1.53 1999/06/12 19:22:40 tgl Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  *  INTERFACE ROUTINES
  16.  * ExecEvalExpr - evaluate an expression and return a datum
  17.  * ExecQual - return true/false if qualification is satisified
  18.  * ExecTargetList - form a new tuple by projecting the given tuple
  19.  *
  20.  *  NOTES
  21.  * ExecEvalExpr() and ExecEvalVar() are hotspots. making these faster
  22.  * will speed up the entire system.  Unfortunately they are currently
  23.  * implemented recursively.  Eliminating the recursion is bound to
  24.  * improve the speed of the executor.
  25.  *
  26.  * ExecTargetList() is used to make tuple projections.  Rather then
  27.  * trying to speed it up, the execution plan should be pre-processed
  28.  * to facilitate attribute sharing between nodes wherever possible,
  29.  * instead of doing needless copying. -cim 5/31/91
  30.  *
  31.  */
  32. #include <string.h>
  33. #include "postgres.h"
  34. #include "access/heapam.h"
  35. #include "catalog/pg_language.h"
  36. #include "executor/execdebug.h"
  37. #include "executor/executor.h"
  38. #include "executor/execFlatten.h"
  39. #include "executor/functions.h"
  40. #include "executor/nodeSubplan.h"
  41. #include "fmgr.h"
  42. #include "nodes/memnodes.h"
  43. #include "nodes/primnodes.h"
  44. #include "nodes/relation.h"
  45. #include "optimizer/clauses.h"
  46. #include "utils/array.h"
  47. #include "utils/builtins.h"
  48. #include "utils/fcache.h"
  49. #include "utils/fcache2.h"
  50. #include "utils/mcxt.h"
  51. #include "utils/memutils.h"
  52. /*
  53.  * externs and constants
  54.  */
  55. /*
  56.  * XXX Used so we can get rid of use of Const nodes in the executor.
  57.  * Currently only used by ExecHashGetBucket and set only by ExecMakeVarConst
  58.  * and by ExecEvalArrayRef.
  59.  */
  60. bool execConstByVal;
  61. int execConstLen;
  62. /* static functions decls */
  63. static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull);
  64. static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
  65.  bool *isNull, bool *isDone);
  66. static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
  67. static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
  68.  bool *isNull, bool *isDone);
  69. static void ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext,
  70.  List *argList, Datum argV[], bool *argIsDone);
  71. static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
  72. static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
  73.  bool *isNull);
  74. static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
  75. static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
  76. static Datum ExecMakeFunctionResult(Node *node, List *arguments,
  77.    ExprContext *econtext, bool *isNull, bool *isDone);
  78. static bool ExecQualClause(Node *clause, ExprContext *econtext);
  79. /*
  80.  *   ExecEvalArrayRef
  81.  *
  82.  *    This function takes an ArrayRef and returns a Const Node if it
  83.  *    is an array reference or returns the changed Array Node if it is
  84.  *    an array assignment.
  85.  */
  86. static Datum
  87. ExecEvalArrayRef(ArrayRef *arrayRef,
  88.  ExprContext *econtext,
  89.  bool *isNull,
  90.  bool *isDone)
  91. {
  92. bool dummy;
  93. int i = 0,
  94. j = 0;
  95. ArrayType  *array_scanner;
  96. List    *upperIndexpr,
  97.    *lowerIndexpr;
  98. Node    *assgnexpr;
  99. List    *elt;
  100. IntArray upper,
  101. lower;
  102. int    *lIndex;
  103. char    *dataPtr;
  104. *isNull = false;
  105. array_scanner = (ArrayType *) ExecEvalExpr(arrayRef->refexpr,
  106.    econtext,
  107.    isNull,
  108.    isDone);
  109. if (*isNull)
  110. return (Datum) NULL;
  111. upperIndexpr = arrayRef->refupperindexpr;
  112. foreach(elt, upperIndexpr)
  113. {
  114. upper.indx[i++] = (int32) ExecEvalExpr((Node *) lfirst(elt),
  115.    econtext,
  116.    isNull,
  117.    &dummy);
  118. if (*isNull)
  119. return (Datum) NULL;
  120. }
  121. lowerIndexpr = arrayRef->reflowerindexpr;
  122. lIndex = NULL;
  123. if (lowerIndexpr != NIL)
  124. {
  125. foreach(elt, lowerIndexpr)
  126. {
  127. lower.indx[j++] = (int32) ExecEvalExpr((Node *) lfirst(elt),
  128.    econtext,
  129.    isNull,
  130.    &dummy);
  131. if (*isNull)
  132. return (Datum) NULL;
  133. }
  134. if (i != j)
  135. elog(ERROR,
  136.  "ExecEvalArrayRef: upper and lower indices mismatch");
  137. lIndex = lower.indx;
  138. }
  139. assgnexpr = arrayRef->refassgnexpr;
  140. if (assgnexpr != NULL)
  141. {
  142. dataPtr = (char *) ExecEvalExpr((Node *)
  143. assgnexpr, econtext,
  144. isNull, &dummy);
  145. if (*isNull)
  146. return (Datum) NULL;
  147. execConstByVal = arrayRef->refelembyval;
  148. execConstLen = arrayRef->refelemlength;
  149. if (lIndex == NULL)
  150. return (Datum) array_set(array_scanner, i, upper.indx, dataPtr,
  151.  arrayRef->refelembyval,
  152.  arrayRef->refelemlength,
  153.  arrayRef->refattrlength, isNull);
  154. return (Datum) array_assgn(array_scanner, i, upper.indx,
  155.    lower.indx,
  156.    (ArrayType *) dataPtr,
  157.    arrayRef->refelembyval,
  158.    arrayRef->refelemlength, isNull);
  159. }
  160. execConstByVal = arrayRef->refelembyval;
  161. execConstLen = arrayRef->refelemlength;
  162. if (lIndex == NULL)
  163. return (Datum) array_ref(array_scanner, i, upper.indx,
  164.  arrayRef->refelembyval,
  165.  arrayRef->refelemlength,
  166.  arrayRef->refattrlength, isNull);
  167. return (Datum) array_clip(array_scanner, i, upper.indx, lower.indx,
  168.   arrayRef->refelembyval,
  169.   arrayRef->refelemlength, isNull);
  170. }
  171. /* ----------------------------------------------------------------
  172.  * ExecEvalAggref
  173.  *
  174.  * Returns a Datum whose value is the value of the precomputed
  175.  * aggregate found in the given expression context.
  176.  * ----------------------------------------------------------------
  177.  */
  178. static Datum
  179. ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull)
  180. {
  181. *isNull = econtext->ecxt_nulls[aggref->aggno];
  182. return econtext->ecxt_values[aggref->aggno];
  183. }
  184. /* ----------------------------------------------------------------
  185.  * ExecEvalVar
  186.  *
  187.  * Returns a Datum whose value is the value of a range
  188.  * variable with respect to given expression context.
  189.  *
  190.  *
  191.  * As an entry condition, we expect that the datatype the
  192.  * plan expects to get (as told by our "variable" argument) is in
  193.  * fact the datatype of the attribute the plan says to fetch (as
  194.  * seen in the current context, identified by our "econtext"
  195.  * argument).
  196.  *
  197.  * If we fetch a Type A attribute and Caller treats it as if it
  198.  * were Type B, there will be undefined results (e.g. crash).
  199.  * One way these might mismatch now is that we're accessing a
  200.  * catalog class and the type information in the pg_attribute
  201.  * class does not match the hardcoded pg_attribute information
  202.  * (in pg_attribute.h) for the class in question.
  203.  *
  204.  * We have an Assert to make sure this entry condition is met.
  205.  *
  206.  * ---------------------------------------------------------------- */
  207. static Datum
  208. ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
  209. {
  210. Datum result;
  211. TupleTableSlot *slot;
  212. AttrNumber attnum;
  213. HeapTuple heapTuple;
  214. TupleDesc tuple_type;
  215. Buffer buffer;
  216. bool byval;
  217. int16 len;
  218. /*
  219.  * get the slot we want
  220.  */
  221. switch (variable->varno)
  222. {
  223. case INNER: /* get the tuple from the inner node */
  224. slot = econtext->ecxt_innertuple;
  225. break;
  226. case OUTER: /* get the tuple from the outer node */
  227. slot = econtext->ecxt_outertuple;
  228. break;
  229. default: /* get the tuple from the relation being
  230.  * scanned */
  231. slot = econtext->ecxt_scantuple;
  232. break;
  233. }
  234. /*
  235.  * extract tuple information from the slot
  236.  */
  237. heapTuple = slot->val;
  238. tuple_type = slot->ttc_tupleDescriptor;
  239. buffer = slot->ttc_buffer;
  240. attnum = variable->varattno;
  241. /* (See prolog for explanation of this Assert) */
  242. Assert(attnum <= 0 ||
  243.    (attnum - 1 <= tuple_type->natts - 1 &&
  244. tuple_type->attrs[attnum - 1] != NULL &&
  245. variable->vartype == tuple_type->attrs[attnum - 1]->atttypid))
  246. /*
  247.  * If the attribute number is invalid, then we are supposed to return
  248.  * the entire tuple, we give back a whole slot so that callers know
  249.  * what the tuple looks like.
  250.  */
  251. if (attnum == InvalidAttrNumber)
  252. {
  253. TupleTableSlot *tempSlot;
  254. TupleDesc td;
  255. HeapTuple tup;
  256. tempSlot = makeNode(TupleTableSlot);
  257. tempSlot->ttc_shouldFree = false;
  258. tempSlot->ttc_descIsNew = true;
  259. tempSlot->ttc_tupleDescriptor = (TupleDesc) NULL;
  260. tempSlot->ttc_buffer = InvalidBuffer;
  261. tempSlot->ttc_whichplan = -1;
  262. tup = heap_copytuple(heapTuple);
  263. td = CreateTupleDescCopy(slot->ttc_tupleDescriptor);
  264. ExecSetSlotDescriptor(tempSlot, td);
  265. ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
  266. return (Datum) tempSlot;
  267. }
  268. result = heap_getattr(heapTuple, /* tuple containing attribute */
  269.   attnum, /* attribute number of desired
  270.  * attribute */
  271.   tuple_type, /* tuple descriptor of tuple */
  272.   isNull); /* return: is attribute null? */
  273. /*
  274.  * return null if att is null
  275.  */
  276. if (*isNull)
  277. return (Datum) NULL;
  278. /*
  279.  * get length and type information.. ??? what should we do about
  280.  * variable length attributes - variable length attributes have their
  281.  * length stored in the first 4 bytes of the memory pointed to by the
  282.  * returned value.. If we can determine that the type is a variable
  283.  * length type, we can do the right thing. -cim 9/15/89
  284.  */
  285. if (attnum < 0)
  286. {
  287. /*
  288.  * If this is a pseudo-att, we get the type and fake the length.
  289.  * There ought to be a routine to return the real lengths, so
  290.  * we'll mark this one ... XXX -mao
  291.  */
  292. len = heap_sysattrlen(attnum); /* XXX see -mao above */
  293. byval = heap_sysattrbyval(attnum); /* XXX see -mao above */
  294. }
  295. else
  296. {
  297. len = tuple_type->attrs[attnum - 1]->attlen;
  298. byval = tuple_type->attrs[attnum - 1]->attbyval ? true : false;
  299. }
  300. execConstByVal = byval;
  301. execConstLen = len;
  302. return result;
  303. }
  304. /* ----------------------------------------------------------------
  305.  * ExecEvalParam
  306.  *
  307.  * Returns the value of a parameter.  A param node contains
  308.  * something like ($.name) and the expression context contains
  309.  * the current parameter bindings (name = "sam") (age = 34)...
  310.  * so our job is to replace the param node with the datum
  311.  * containing the appropriate information ("sam").
  312.  *
  313.  * Q: if we have a parameter ($.foo) without a binding, i.e.
  314.  *    there is no (foo = xxx) in the parameter list info,
  315.  *    is this a fatal error or should this be a "not available"
  316.  *    (in which case we shoud return a Const node with the
  317.  * isnull flag) ? -cim 10/13/89
  318.  *
  319.  * Minor modification: Param nodes now have an extra field,
  320.  * `paramkind' which specifies the type of parameter
  321.  * (see params.h). So while searching the paramList for
  322.  * a paramname/value pair, we have also to check for `kind'.
  323.  *
  324.  * NOTE: The last entry in `paramList' is always an
  325.  * entry with kind == PARAM_INVALID.
  326.  * ----------------------------------------------------------------
  327.  */
  328. Datum
  329. ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
  330. {
  331. char    *thisParameterName;
  332. int thisParameterKind = expression->paramkind;
  333. AttrNumber thisParameterId = expression->paramid;
  334. int matchFound;
  335. ParamListInfo paramList;
  336. if (thisParameterKind == PARAM_EXEC)
  337. {
  338. ParamExecData *prm = &(econtext->ecxt_param_exec_vals[thisParameterId]);
  339. if (prm->execPlan != NULL)
  340. ExecSetParamPlan(prm->execPlan);
  341. Assert(prm->execPlan == NULL);
  342. *isNull = prm->isnull;
  343. return prm->value;
  344. }
  345. thisParameterName = expression->paramname;
  346. paramList = econtext->ecxt_param_list_info;
  347. *isNull = false;
  348. /*
  349.  * search the list with the parameter info to find a matching name. An
  350.  * entry with an InvalidName denotes the last element in the array.
  351.  */
  352. matchFound = 0;
  353. if (paramList != NULL)
  354. {
  355. /*
  356.  * search for an entry in 'paramList' that matches the
  357.  * `expression'.
  358.  */
  359. while (paramList->kind != PARAM_INVALID && !matchFound)
  360. {
  361. switch (thisParameterKind)
  362. {
  363. case PARAM_NAMED:
  364. if (thisParameterKind == paramList->kind &&
  365. strcmp(paramList->name, thisParameterName) == 0)
  366. matchFound = 1;
  367. break;
  368. case PARAM_NUM:
  369. if (thisParameterKind == paramList->kind &&
  370. paramList->id == thisParameterId)
  371. matchFound = 1;
  372. break;
  373. case PARAM_OLD:
  374. case PARAM_NEW:
  375. if (thisParameterKind == paramList->kind &&
  376. paramList->id == thisParameterId)
  377. {
  378. matchFound = 1;
  379. /*
  380.  * sanity check
  381.  */
  382. if (strcmp(paramList->name, thisParameterName) != 0)
  383. {
  384. elog(ERROR,
  385.  "ExecEvalParam: new/old params with same id & diff names");
  386. }
  387. }
  388. break;
  389. default:
  390. /*
  391.  * oops! this is not supposed to happen!
  392.  */
  393. elog(ERROR, "ExecEvalParam: invalid paramkind %d",
  394.  thisParameterKind);
  395. }
  396. if (!matchFound)
  397. paramList++;
  398. } /* while */
  399. } /* if */
  400. if (!matchFound)
  401. {
  402. /*
  403.  * ooops! we couldn't find this parameter in the parameter list.
  404.  * Signal an error
  405.  */
  406. elog(ERROR, "ExecEvalParam: Unknown value for parameter %s",
  407.  thisParameterName);
  408. }
  409. /*
  410.  * return the value.
  411.  */
  412. if (paramList->isnull)
  413. {
  414. *isNull = true;
  415. return (Datum) NULL;
  416. }
  417. if (expression->param_tlist != NIL)
  418. {
  419. HeapTuple tup;
  420. Datum value;
  421. List    *tlist = expression->param_tlist;
  422. TargetEntry *tle = (TargetEntry *) lfirst(tlist);
  423. TupleTableSlot *slot = (TupleTableSlot *) paramList->value;
  424. tup = slot->val;
  425. value = ProjectAttribute(slot->ttc_tupleDescriptor,
  426.  tle, tup, isNull);
  427. return value;
  428. }
  429. return paramList->value;
  430. }
  431. /* ----------------------------------------------------------------
  432.  * ExecEvalOper / ExecEvalFunc support routines
  433.  * ----------------------------------------------------------------
  434.  */
  435. /*
  436.  * GetAttributeByName
  437.  * GetAttributeByNum
  438.  *
  439.  * These are functions which return the value of the
  440.  * named attribute out of the tuple from the arg slot.  User defined
  441.  * C functions which take a tuple as an argument are expected
  442.  * to use this.  Ex: overpaid(EMP) might call GetAttributeByNum().
  443.  */
  444. /* static but gets called from external functions */
  445. char *
  446. GetAttributeByNum(TupleTableSlot *slot,
  447.   AttrNumber attrno,
  448.   bool *isNull)
  449. {
  450. Datum retval;
  451. if (!AttributeNumberIsValid(attrno))
  452. elog(ERROR, "GetAttributeByNum: Invalid attribute number");
  453. if (!AttrNumberIsForUserDefinedAttr(attrno))
  454. elog(ERROR, "GetAttributeByNum: cannot access system attributes here");
  455. if (isNull == (bool *) NULL)
  456. elog(ERROR, "GetAttributeByNum: a NULL isNull flag was passed");
  457. if (TupIsNull(slot))
  458. {
  459. *isNull = true;
  460. return (char *) NULL;
  461. }
  462. retval = heap_getattr(slot->val,
  463.   attrno,
  464.   slot->ttc_tupleDescriptor,
  465.   isNull);
  466. if (*isNull)
  467. return (char *) NULL;
  468. return (char *) retval;
  469. }
  470. /* XXX name for catalogs */
  471. #ifdef NOT_USED
  472. char *
  473. att_by_num(TupleTableSlot *slot,
  474.    AttrNumber attrno,
  475.    bool *isNull)
  476. {
  477. return GetAttributeByNum(slot, attrno, isNull);
  478. }
  479. #endif
  480. char *
  481. GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
  482. {
  483. AttrNumber attrno;
  484. TupleDesc tupdesc;
  485. Datum retval;
  486. int natts;
  487. int i;
  488. if (attname == NULL)
  489. elog(ERROR, "GetAttributeByName: Invalid attribute name");
  490. if (isNull == (bool *) NULL)
  491. elog(ERROR, "GetAttributeByName: a NULL isNull flag was passed");
  492. if (TupIsNull(slot))
  493. {
  494. *isNull = true;
  495. return (char *) NULL;
  496. }
  497. tupdesc = slot->ttc_tupleDescriptor;
  498. natts = slot->val->t_data->t_natts;
  499. attrno = InvalidAttrNumber;
  500. for (i = 0; i < tupdesc->natts; i++)
  501. {
  502. if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0)
  503. {
  504. attrno = tupdesc->attrs[i]->attnum;
  505. break;
  506. }
  507. }
  508. if (attrno == InvalidAttrNumber)
  509. elog(ERROR, "GetAttributeByName: attribute %s not found", attname);
  510. retval = heap_getattr(slot->val,
  511.   attrno,
  512.   tupdesc,
  513.   isNull);
  514. if (*isNull)
  515. return (char *) NULL;
  516. return (char *) retval;
  517. }
  518. /* XXX name for catalogs */
  519. #ifdef NOT_USED
  520. char *
  521. att_by_name(TupleTableSlot *slot, char *attname, bool *isNull)
  522. {
  523. return GetAttributeByName(slot, attname, isNull);
  524. }
  525. #endif
  526. static void
  527. ExecEvalFuncArgs(FunctionCachePtr fcache,
  528.  ExprContext *econtext,
  529.  List *argList,
  530.  Datum argV[],
  531.  bool *argIsDone)
  532. {
  533. int i;
  534. bool argIsNull,
  535.    *nullVect;
  536. List    *arg;
  537. nullVect = fcache->nullVect;
  538. i = 0;
  539. foreach(arg, argList)
  540. {
  541. /*
  542.  * evaluate the expression, in general functions cannot take sets
  543.  * as arguments but we make an exception in the case of nested dot
  544.  * expressions.  We have to watch out for this case here.
  545.  */
  546. argV[i] = (Datum)
  547. ExecEvalExpr((Node *) lfirst(arg),
  548.  econtext,
  549.  &argIsNull,
  550.  argIsDone);
  551. if (!(*argIsDone))
  552. {
  553. Assert(i == 0);
  554. fcache->setArg = (char *) argV[0];
  555. fcache->hasSetArg = true;
  556. }
  557. if (argIsNull)
  558. nullVect[i] = true;
  559. else
  560. nullVect[i] = false;
  561. i++;
  562. }
  563. }
  564. /*
  565.  * ExecMakeFunctionResult
  566.  */
  567. static Datum
  568. ExecMakeFunctionResult(Node *node,
  569.    List *arguments,
  570.    ExprContext *econtext,
  571.    bool *isNull,
  572.    bool *isDone)
  573. {
  574. Datum argV[MAXFMGRARGS];
  575. FunctionCachePtr fcache;
  576. Func    *funcNode = NULL;
  577. Oper    *operNode = NULL;
  578. bool funcisset = false;
  579. /*
  580.  * This is kind of ugly, Func nodes now have targetlists so that we
  581.  * know when and what to project out from postquel function results.
  582.  * This means we have to pass the func node all the way down instead
  583.  * of using only the fcache struct as before.  ExecMakeFunctionResult
  584.  * becomes a little bit more of a dual personality as a result.
  585.  */
  586. if (IsA(node, Func))
  587. {
  588. funcNode = (Func *) node;
  589. fcache = funcNode->func_fcache;
  590. }
  591. else
  592. {
  593. operNode = (Oper *) node;
  594. fcache = operNode->op_fcache;
  595. }
  596. /*
  597.  * arguments is a list of expressions to evaluate before passing to
  598.  * the function manager. We collect the results of evaluating the
  599.  * expressions into a datum array (argV) and pass this array to
  600.  * arrayFmgr()
  601.  */
  602. if (fcache->nargs != 0)
  603. {
  604. bool argDone;
  605. if (fcache->nargs > MAXFMGRARGS)
  606. elog(ERROR, "ExecMakeFunctionResult: too many arguments");
  607. /*
  608.  * If the setArg in the fcache is set we have an argument
  609.  * returning a set of tuples (i.e. a nested dot expression).  We
  610.  * don't want to evaluate the arguments again until the function
  611.  * is done. hasSetArg will always be false until we eval the args
  612.  * for the first time. We should set this in the parser.
  613.  */
  614. if ((fcache->hasSetArg) && fcache->setArg != NULL)
  615. {
  616. argV[0] = (Datum) fcache->setArg;
  617. argDone = false;
  618. }
  619. else
  620. ExecEvalFuncArgs(fcache, econtext, arguments, argV, &argDone);
  621. if ((fcache->hasSetArg) && (argDone))
  622. {
  623. if (isDone)
  624. *isDone = true;
  625. return (Datum) NULL;
  626. }
  627. }
  628. /*
  629.  * If this function is really a set, we have to diddle with things. If
  630.  * the function has already been called at least once, then the setArg
  631.  * field of the fcache holds the OID of this set in pg_proc.  (This is
  632.  * not quite legit, since the setArg field is really for functions
  633.  * which take sets of tuples as input - set functions take no inputs
  634.  * at all. But it's a nice place to stash this value, for now.)
  635.  *
  636.  * If this is the first call of the set's function, then the call to
  637.  * ExecEvalFuncArgs above just returned the OID of the pg_proc tuple
  638.  * which defines this set. So replace the existing funcid in the
  639.  * funcnode with the set's OID.  Also, we want a new fcache which
  640.  * points to the right function, so get that, now that we have the
  641.  * right OID.  Also zero out the argV, since the real set doesn't take
  642.  * any arguments.
  643.  */
  644. if (((Func *) node)->funcid == F_SETEVAL)
  645. {
  646. funcisset = true;
  647. if (fcache->setArg)
  648. {
  649. argV[0] = 0;
  650. ((Func *) node)->funcid = (Oid) PointerGetDatum(fcache->setArg);
  651. }
  652. else
  653. {
  654. ((Func *) node)->funcid = (Oid) argV[0];
  655. setFcache(node, argV[0], NIL, econtext);
  656. fcache = ((Func *) node)->func_fcache;
  657. fcache->setArg = (char *) argV[0];
  658. argV[0] = (Datum) 0;
  659. }
  660. }
  661. /*
  662.  * now return the value gotten by calling the function manager,
  663.  * passing the function the evaluated parameter values.
  664.  */
  665. if (fcache->language == SQLlanguageId)
  666. {
  667. Datum result;
  668. Assert(funcNode);
  669. result = postquel_function(funcNode, (char **) argV, isNull, isDone);
  670. /*
  671.  * finagle the situation where we are iterating through all
  672.  * results in a nested dot function (whose argument function
  673.  * returns a set of tuples) and the current function finally
  674.  * finishes.  We need to get the next argument in the set and run
  675.  * the function all over again.  This is getting unclean.
  676.  */
  677. if ((*isDone) && (fcache->hasSetArg))
  678. {
  679. bool argDone;
  680. ExecEvalFuncArgs(fcache, econtext, arguments, argV, &argDone);
  681. if (argDone)
  682. {
  683. fcache->setArg = (char *) NULL;
  684. *isDone = true;
  685. result = (Datum) NULL;
  686. }
  687. else
  688. result = postquel_function(funcNode,
  689.    (char **) argV,
  690.    isNull,
  691.    isDone);
  692. }
  693. if (funcisset)
  694. {
  695. /*
  696.  * reset the funcid so that next call to this routine will
  697.  * still recognize this func as a set. Note that for now we
  698.  * assume that the set function in pg_proc must be a Postquel
  699.  * function - the funcid is not reset below for C functions.
  700.  */
  701. ((Func *) node)->funcid = F_SETEVAL;
  702. /*
  703.  * If we're done with the results of this function, get rid of
  704.  * its func cache.
  705.  */
  706. if (*isDone)
  707. ((Func *) node)->func_fcache = NULL;
  708. }
  709. return result;
  710. }
  711. else
  712. {
  713. int i;
  714. if (isDone)
  715. *isDone = true;
  716. for (i = 0; i < fcache->nargs; i++)
  717. if (fcache->nullVect[i] == true)
  718. *isNull = true;
  719. return (Datum) fmgr_c(&fcache->func, (FmgrValues *) argV, isNull);
  720. }
  721. }
  722. /* ----------------------------------------------------------------
  723.  * ExecEvalOper
  724.  * ExecEvalFunc
  725.  *
  726.  * Evaluate the functional result of a list of arguments by calling the
  727.  * function manager.  Note that in the case of operator expressions, the
  728.  * optimizer had better have already replaced the operator OID with the
  729.  * appropriate function OID or we're hosed.
  730.  *
  731.  * old comments
  732.  * Presumably the function manager will not take null arguments, so we
  733.  * check for null arguments before sending the arguments to (fmgr).
  734.  *
  735.  * Returns the value of the functional expression.
  736.  * ----------------------------------------------------------------
  737.  */
  738. /* ----------------------------------------------------------------
  739.  * ExecEvalOper
  740.  * ----------------------------------------------------------------
  741.  */
  742. static Datum
  743. ExecEvalOper(Expr *opClause, ExprContext *econtext, bool *isNull)
  744. {
  745. Oper    *op;
  746. List    *argList;
  747. FunctionCachePtr fcache;
  748. bool isDone;
  749. /*
  750.  * an opclause is a list (op args).  (I think)
  751.  *
  752.  * we extract the oid of the function associated with the op and then
  753.  * pass the work onto ExecMakeFunctionResult which evaluates the
  754.  * arguments and returns the result of calling the function on the
  755.  * evaluated arguments.
  756.  */
  757. op = (Oper *) opClause->oper;
  758. argList = opClause->args;
  759. /*
  760.  * get the fcache from the Oper node. If it is NULL, then initialize
  761.  * it
  762.  */
  763. fcache = op->op_fcache;
  764. if (fcache == NULL)
  765. {
  766. setFcache((Node *) op, op->opid, argList, econtext);
  767. fcache = op->op_fcache;
  768. }
  769. /*
  770.  * call ExecMakeFunctionResult() with a dummy isDone that we ignore.
  771.  * We don't have operator whose arguments are sets.
  772.  */
  773. return ExecMakeFunctionResult((Node *) op, argList, econtext, isNull, &isDone);
  774. }
  775. /* ----------------------------------------------------------------
  776.  * ExecEvalFunc
  777.  * ----------------------------------------------------------------
  778.  */
  779. static Datum
  780. ExecEvalFunc(Expr *funcClause,
  781.  ExprContext *econtext,
  782.  bool *isNull,
  783.  bool *isDone)
  784. {
  785. Func    *func;
  786. List    *argList;
  787. FunctionCachePtr fcache;
  788. /*
  789.  * an funcclause is a list (func args).  (I think)
  790.  *
  791.  * we extract the oid of the function associated with the func node and
  792.  * then pass the work onto ExecMakeFunctionResult which evaluates the
  793.  * arguments and returns the result of calling the function on the
  794.  * evaluated arguments.
  795.  *
  796.  * this is nearly identical to the ExecEvalOper code.
  797.  */
  798. func = (Func *) funcClause->oper;
  799. argList = funcClause->args;
  800. /*
  801.  * get the fcache from the Func node. If it is NULL, then initialize
  802.  * it
  803.  */
  804. fcache = func->func_fcache;
  805. if (fcache == NULL)
  806. {
  807. setFcache((Node *) func, func->funcid, argList, econtext);
  808. fcache = func->func_fcache;
  809. }
  810. return ExecMakeFunctionResult((Node *) func, argList, econtext, isNull, isDone);
  811. }
  812. /* ----------------------------------------------------------------
  813.  * ExecEvalNot
  814.  * ExecEvalOr
  815.  * ExecEvalAnd
  816.  *
  817.  * Evaluate boolean expressions.  Evaluation of 'or' is
  818.  * short-circuited when the first true (or null) value is found.
  819.  *
  820.  * The query planner reformulates clause expressions in the
  821.  * qualification to conjunctive normal form.  If we ever get
  822.  * an AND to evaluate, we can be sure that it's not a top-level
  823.  * clause in the qualification, but appears lower (as a function
  824.  * argument, for example), or in the target list. Not that you
  825.  * need to know this, mind you...
  826.  * ----------------------------------------------------------------
  827.  */
  828. static Datum
  829. ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
  830. {
  831. Datum expr_value;
  832. Node    *clause;
  833. bool isDone;
  834. clause = lfirst(notclause->args);
  835. /*
  836.  * We don't iterate over sets in the quals, so pass in an isDone flag,
  837.  * but ignore it.
  838.  */
  839. expr_value = ExecEvalExpr(clause, econtext, isNull, &isDone);
  840. /*
  841.  * if the expression evaluates to null, then we just cascade the null
  842.  * back to whoever called us.
  843.  */
  844. if (*isNull)
  845. return expr_value;
  846. /*
  847.  * evaluation of 'not' is simple.. expr is false, then return 'true'
  848.  * and vice versa.
  849.  */
  850. if (DatumGetInt32(expr_value) == 0)
  851. return (Datum) true;
  852. return (Datum) false;
  853. }
  854. /* ----------------------------------------------------------------
  855.  * ExecEvalOr
  856.  * ----------------------------------------------------------------
  857.  */
  858. static Datum
  859. ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
  860. {
  861. List    *clauses;
  862. List    *clause;
  863. bool isDone;
  864. bool IsNull;
  865. Datum const_value = 0;
  866. IsNull = false;
  867. clauses = orExpr->args;
  868. /*
  869.  * we use three valued logic functions here... we evaluate each of the
  870.  * clauses in turn, as soon as one is true we return that value.  If
  871.  * none is true and  none of the clauses evaluate to NULL we return
  872.  * the value of the last clause evaluated (which should be false) with
  873.  * *isNull set to false else if none is true and at least one clause
  874.  * evaluated to NULL we set *isNull flag to true -
  875.  */
  876. foreach(clause, clauses)
  877. {
  878. /*
  879.  * We don't iterate over sets in the quals, so pass in an isDone
  880.  * flag, but ignore it.
  881.  */
  882. const_value = ExecEvalExpr((Node *) lfirst(clause),
  883.    econtext,
  884.    isNull,
  885.    &isDone);
  886. /*
  887.  * if the expression evaluates to null, then we remember it in the
  888.  * local IsNull flag, if none of the clauses are true then we need
  889.  * to set *isNull to true again.
  890.  */
  891. if (*isNull)
  892. {
  893. IsNull = *isNull;
  894. /*
  895.  * Many functions don't (or can't!) check if an argument is
  896.  * NULL or NOT_NULL and may return TRUE (1) with *isNull TRUE
  897.  * (an_int4_column <> 1: int4ne returns TRUE for NULLs). Not
  898.  * having time to fix the function manager I want to fix OR:
  899.  * if we had 'x <> 1 OR x isnull' then when x is NULL TRUE was
  900.  * returned by the 'x <> 1' clause ... but ExecQualClause says
  901.  * that the qualification should *fail* if isnull is TRUE for
  902.  * any value returned by ExecEvalExpr. So, force this rule
  903.  * here: if isnull is TRUE then the clause failed. Note:
  904.  * nullvalue() & nonnullvalue() always sets isnull to FALSE
  905.  * for NULLs. - vadim 09/22/97
  906.  */
  907. const_value = 0;
  908. }
  909. /*
  910.  * if we have a true result, then we return it.
  911.  */
  912. if (DatumGetInt32(const_value) != 0)
  913. return const_value;
  914. }
  915. /* IsNull is true if at least one clause evaluated to NULL */
  916. *isNull = IsNull;
  917. return const_value;
  918. }
  919. /* ----------------------------------------------------------------
  920.  * ExecEvalAnd
  921.  * ----------------------------------------------------------------
  922.  */
  923. static Datum
  924. ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
  925. {
  926. List    *clauses;
  927. List    *clause;
  928. Datum const_value = 0;
  929. bool isDone;
  930. bool IsNull;
  931. IsNull = false;
  932. clauses = andExpr->args;
  933. /*
  934.  * we evaluate each of the clauses in turn, as soon as one is false we
  935.  * return that value.  If none are false or NULL then we return the
  936.  * value of the last clause evaluated, which should be true.
  937.  */
  938. foreach(clause, clauses)
  939. {
  940. /*
  941.  * We don't iterate over sets in the quals, so pass in an isDone
  942.  * flag, but ignore it.
  943.  */
  944. const_value = ExecEvalExpr((Node *) lfirst(clause),
  945.    econtext,
  946.    isNull,
  947.    &isDone);
  948. /*
  949.  * if the expression evaluates to null, then we remember it in
  950.  * IsNull, if none of the clauses after this evaluates to false we
  951.  * will have to set *isNull to true again.
  952.  */
  953. if (*isNull)
  954. IsNull = *isNull;
  955. /*
  956.  * if we have a false result, then we return it, since the
  957.  * conjunction must be false.
  958.  */
  959. if (DatumGetInt32(const_value) == 0)
  960. return const_value;
  961. }
  962. *isNull = IsNull;
  963. return const_value;
  964. }
  965. /* ----------------------------------------------------------------
  966.  * ExecEvalCase
  967.  *
  968.  * Evaluate a CASE clause. Will have boolean expressions
  969.  * inside the WHEN clauses, and will have constants
  970.  * for results.
  971.  * - thomas 1998-11-09
  972.  * ----------------------------------------------------------------
  973.  */
  974. static Datum
  975. ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
  976. {
  977. List    *clauses;
  978. List    *clause;
  979. CaseWhen   *wclause;
  980. Datum const_value = 0;
  981. bool isDone;
  982. clauses = caseExpr->args;
  983. /*
  984.  * we evaluate each of the WHEN clauses in turn, as soon as one is
  985.  * true we return the corresponding result. If none are true then we
  986.  * return the value of the default clause, or NULL.
  987.  */
  988. foreach(clause, clauses)
  989. {
  990. /*
  991.  * We don't iterate over sets in the quals, so pass in an isDone
  992.  * flag, but ignore it.
  993.  */
  994. wclause = lfirst(clause);
  995. const_value = ExecEvalExpr((Node *) wclause->expr,
  996.    econtext,
  997.    isNull,
  998.    &isDone);
  999. /*
  1000.  * if we have a true test, then we return the result, since the
  1001.  * case statement is satisfied.
  1002.  */
  1003. if (DatumGetInt32(const_value) != 0)
  1004. {
  1005. const_value = ExecEvalExpr((Node *) wclause->result,
  1006.    econtext,
  1007.    isNull,
  1008.    &isDone);
  1009. return (Datum) const_value;
  1010. }
  1011. }
  1012. if (caseExpr->defresult)
  1013. {
  1014. const_value = ExecEvalExpr((Node *) caseExpr->defresult,
  1015.    econtext,
  1016.    isNull,
  1017.    &isDone);
  1018. }
  1019. else
  1020. *isNull = true;
  1021. return const_value;
  1022. }
  1023. /* ----------------------------------------------------------------
  1024.  * ExecEvalExpr
  1025.  *
  1026.  * Recursively evaluate a targetlist or qualification expression.
  1027.  *
  1028.  * This routine is an inner loop routine and should be as fast
  1029.  * as possible.
  1030.  *
  1031.  * Node comparison functions were replaced by macros for speed and to plug
  1032.  * memory leaks incurred by using the planner's Lispy stuff for
  1033.  * comparisons.  Order of evaluation of node comparisons IS IMPORTANT;
  1034.  * the macros do no checks.  Order of evaluation:
  1035.  *
  1036.  * o an isnull check, largely to avoid coredumps since greg doubts this
  1037.  *   routine is called with a null ptr anyway in proper operation, but is
  1038.  *   not completely sure...
  1039.  * o ExactNodeType checks.
  1040.  * o clause checks or other checks where we look at the lfirst of something.
  1041.  * ----------------------------------------------------------------
  1042.  */
  1043. Datum
  1044. ExecEvalExpr(Node *expression,
  1045.  ExprContext *econtext,
  1046.  bool *isNull,
  1047.  bool *isDone)
  1048. {
  1049. Datum retDatum = 0;
  1050. *isNull = false;
  1051. /*
  1052.  * Some callers don't care about is done and only want 1 result.  They
  1053.  * indicate this by passing NULL
  1054.  */
  1055. if (isDone)
  1056. *isDone = true;
  1057. /*
  1058.  * here we dispatch the work to the appropriate type of function given
  1059.  * the type of our expression.
  1060.  */
  1061. if (expression == NULL)
  1062. {
  1063. *isNull = true;
  1064. return (Datum) true;
  1065. }
  1066. switch (nodeTag(expression))
  1067. {
  1068. case T_Var:
  1069. retDatum = (Datum) ExecEvalVar((Var *) expression, econtext, isNull);
  1070. break;
  1071. case T_Const:
  1072. {
  1073. Const    *con = (Const *) expression;
  1074. if (con->constisnull)
  1075. *isNull = true;
  1076. retDatum = con->constvalue;
  1077. break;
  1078. }
  1079. case T_Param:
  1080. retDatum = (Datum) ExecEvalParam((Param *) expression, econtext, isNull);
  1081. break;
  1082. case T_Iter:
  1083. retDatum = (Datum) ExecEvalIter((Iter *) expression,
  1084. econtext,
  1085. isNull,
  1086. isDone);
  1087. break;
  1088. case T_Aggref:
  1089. retDatum = (Datum) ExecEvalAggref((Aggref *) expression,
  1090.   econtext,
  1091.   isNull);
  1092. break;
  1093. case T_ArrayRef:
  1094. retDatum = (Datum) ExecEvalArrayRef((ArrayRef *) expression,
  1095. econtext,
  1096. isNull,
  1097. isDone);
  1098. break;
  1099. case T_Expr:
  1100. {
  1101. Expr    *expr = (Expr *) expression;
  1102. switch (expr->opType)
  1103. {
  1104. case OP_EXPR:
  1105. retDatum = (Datum) ExecEvalOper(expr, econtext, isNull);
  1106. break;
  1107. case FUNC_EXPR:
  1108. retDatum = (Datum) ExecEvalFunc(expr, econtext, isNull, isDone);
  1109. break;
  1110. case OR_EXPR:
  1111. retDatum = (Datum) ExecEvalOr(expr, econtext, isNull);
  1112. break;
  1113. case AND_EXPR:
  1114. retDatum = (Datum) ExecEvalAnd(expr, econtext, isNull);
  1115. break;
  1116. case NOT_EXPR:
  1117. retDatum = (Datum) ExecEvalNot(expr, econtext, isNull);
  1118. break;
  1119. case SUBPLAN_EXPR:
  1120. retDatum = (Datum) ExecSubPlan((SubPlan *) expr->oper, expr->args, econtext);
  1121. break;
  1122. default:
  1123. elog(ERROR, "ExecEvalExpr: unknown expression type %d", expr->opType);
  1124. break;
  1125. }
  1126. break;
  1127. }
  1128. case T_CaseExpr:
  1129. retDatum = (Datum) ExecEvalCase((CaseExpr *) expression, econtext, isNull);
  1130. break;
  1131. default:
  1132. elog(ERROR, "ExecEvalExpr: unknown expression type %d", nodeTag(expression));
  1133. break;
  1134. }
  1135. return retDatum;
  1136. } /* ExecEvalExpr() */
  1137. /* ----------------------------------------------------------------
  1138.  *  ExecQual / ExecTargetList
  1139.  * ----------------------------------------------------------------
  1140.  */
  1141. /* ----------------------------------------------------------------
  1142.  * ExecQualClause
  1143.  *
  1144.  * this is a workhorse for ExecQual.  ExecQual has to deal
  1145.  * with a list of qualifications, so it passes each qualification
  1146.  * in the list to this function one at a time.  ExecQualClause
  1147.  * returns true when the qualification *fails* and false if
  1148.  * the qualification succeeded (meaning we have to test the
  1149.  * rest of the qualification)
  1150.  * ----------------------------------------------------------------
  1151.  */
  1152. static bool
  1153. ExecQualClause(Node *clause, ExprContext *econtext)
  1154. {
  1155. Datum expr_value;
  1156. bool isNull;
  1157. bool isDone;
  1158. /* when there is a null clause, consider the qualification to be true */
  1159. if (clause == NULL)
  1160. return true;
  1161. /*
  1162.  * pass isDone, but ignore it. We don't iterate over multiple returns
  1163.  * in the qualifications.
  1164.  */
  1165. expr_value = (Datum)
  1166. ExecEvalExpr(clause, econtext, &isNull, &isDone);
  1167. /*
  1168.  * this is interesting behaviour here. When a clause evaluates to
  1169.  * null, then we consider this as passing the qualification. it seems
  1170.  * kind of like, if the qual is NULL, then there's no qual..
  1171.  */
  1172. if (isNull)
  1173. return true;
  1174. /*
  1175.  * remember, we return true when the qualification fails..
  1176.  */
  1177. if (DatumGetInt32(expr_value) == 0)
  1178. return true;
  1179. return false;
  1180. }
  1181. /* ----------------------------------------------------------------
  1182.  * ExecQual
  1183.  *
  1184.  * Evaluates a conjunctive boolean expression and returns t
  1185.  * iff none of the subexpressions are false (or null).
  1186.  * ----------------------------------------------------------------
  1187.  */
  1188. bool
  1189. ExecQual(List *qual, ExprContext *econtext)
  1190. {
  1191. List    *clause;
  1192. bool result;
  1193. /*
  1194.  * debugging stuff
  1195.  */
  1196. EV_printf("ExecQual: qual is ");
  1197. EV_nodeDisplay(qual);
  1198. EV_printf("n");
  1199. IncrProcessed();
  1200. /*
  1201.  * return true immediately if no qual
  1202.  */
  1203. if (qual == NIL)
  1204. return true;
  1205. /*
  1206.  * a "qual" is a list of clauses.  To evaluate the qual, we evaluate
  1207.  * each of the clauses in the list.
  1208.  *
  1209.  * ExecQualClause returns true when we know the qualification *failed* so
  1210.  * we just pass each clause in qual to it until we know the qual
  1211.  * failed or there are no more clauses.
  1212.  */
  1213. result = false;
  1214. foreach(clause, qual)
  1215. {
  1216. result = ExecQualClause((Node *) lfirst(clause), econtext);
  1217. if (result == true)
  1218. break;
  1219. }
  1220. /*
  1221.  * if result is true, then it means a clause failed so we return
  1222.  * false.  if result is false then it means no clause failed so we
  1223.  * return true.
  1224.  */
  1225. if (result == true)
  1226. return false;
  1227. return true;
  1228. }
  1229. int
  1230. ExecTargetListLength(List *targetlist)
  1231. {
  1232. int len;
  1233. List    *tl;
  1234. TargetEntry *curTle;
  1235. len = 0;
  1236. foreach(tl, targetlist)
  1237. {
  1238. curTle = lfirst(tl);
  1239. if (curTle->resdom != NULL)
  1240. len++;
  1241. else
  1242. len += curTle->fjoin->fj_nNodes;
  1243. }
  1244. return len;
  1245. }
  1246. /* ----------------------------------------------------------------
  1247.  * ExecTargetList
  1248.  *
  1249.  * Evaluates a targetlist with respect to the current
  1250.  * expression context and return a tuple.
  1251.  * ----------------------------------------------------------------
  1252.  */
  1253. static HeapTuple
  1254. ExecTargetList(List *targetlist,
  1255.    int nodomains,
  1256.    TupleDesc targettype,
  1257.    Datum *values,
  1258.    ExprContext *econtext,
  1259.    bool *isDone)
  1260. {
  1261. char nulls_array[64];
  1262. bool fjNullArray[64];
  1263. bool    *fjIsNull;
  1264. char    *null_head;
  1265. List    *tl;
  1266. TargetEntry *tle;
  1267. Node    *expr;
  1268. Resdom    *resdom;
  1269. AttrNumber resind;
  1270. Datum constvalue;
  1271. HeapTuple newTuple;
  1272. bool isNull;
  1273. static struct tupleDesc NullTupleDesc; /* we assume this inits to zeroes */
  1274. /*
  1275.  * debugging stuff
  1276.  */
  1277. EV_printf("ExecTargetList: tl is ");
  1278. EV_nodeDisplay(targetlist);
  1279. EV_printf("n");
  1280. /*
  1281.  * There used to be some klugy and demonstrably broken code here that
  1282.  * special-cased the situation where targetlist == NIL.  Now we just
  1283.  * fall through and return an empty-but-valid tuple.  We do, however,
  1284.  * have to cope with the possibility that targettype is NULL ---
  1285.  * heap_formtuple won't like that, so pass a dummy descriptor with
  1286.  * natts = 0 to deal with it.
  1287.  */
  1288. if (targettype == NULL)
  1289. targettype = &NullTupleDesc;
  1290. /*
  1291.  * allocate an array of char's to hold the "null" information only if
  1292.  * we have a really large targetlist.  otherwise we use the stack.
  1293.  */
  1294. if (nodomains > 64)
  1295. {
  1296. null_head = (char *) palloc(nodomains + 1);
  1297. fjIsNull = (bool *) palloc(nodomains + 1);
  1298. }
  1299. else
  1300. {
  1301. null_head = &nulls_array[0];
  1302. fjIsNull = &fjNullArray[0];
  1303. }
  1304. /*
  1305.  * evaluate all the expressions in the target list
  1306.  */
  1307. EV_printf("ExecTargetList: setting target list valuesn");
  1308. *isDone = true;
  1309. foreach(tl, targetlist)
  1310. {
  1311. /*
  1312.  * remember, a target list is a list of lists:
  1313.  *
  1314.  * ((<resdom | fjoin> expr) (<resdom | fjoin> expr) ...)
  1315.  *
  1316.  * tl is a pointer to successive cdr's of the targetlist tle is a
  1317.  * pointer to the target list entry in tl
  1318.  */
  1319. tle = lfirst(tl);
  1320. if (tle->resdom != NULL)
  1321. {
  1322. expr = tle->expr;
  1323. resdom = tle->resdom;
  1324. resind = resdom->resno - 1;
  1325. constvalue = (Datum) ExecEvalExpr(expr,
  1326.   econtext,
  1327.   &isNull,
  1328.   isDone);
  1329. if ((IsA(expr, Iter)) && (*isDone))
  1330. return (HeapTuple) NULL;
  1331. values[resind] = constvalue;
  1332. if (!isNull)
  1333. null_head[resind] = ' ';
  1334. else
  1335. null_head[resind] = 'n';
  1336. }
  1337. else
  1338. {
  1339. int curNode;
  1340. Resdom    *fjRes;
  1341. List    *fjTlist = (List *) tle->expr;
  1342. Fjoin    *fjNode = tle->fjoin;
  1343. int nNodes = fjNode->fj_nNodes;
  1344. DatumPtr results = fjNode->fj_results;
  1345. ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
  1346. if (*isDone)
  1347. return (HeapTuple) NULL;
  1348. /*
  1349.  * get the result from the inner node
  1350.  */
  1351. fjRes = (Resdom *) fjNode->fj_innerNode;
  1352. resind = fjRes->resno - 1;
  1353. if (fjIsNull[0])
  1354. null_head[resind] = 'n';
  1355. else
  1356. {
  1357. null_head[resind] = ' ';
  1358. values[resind] = results[0];
  1359. }
  1360. /*
  1361.  * Get results from all of the outer nodes
  1362.  */
  1363. for (curNode = 1;
  1364.  curNode < nNodes;
  1365.  curNode++, fjTlist = lnext(fjTlist))
  1366. {
  1367. #ifdef NOT_USED /* what is this?? */
  1368. Node    *outernode = lfirst(fjTlist);
  1369. fjRes = (Resdom *) outernode->iterexpr;
  1370. #endif
  1371. resind = fjRes->resno - 1;
  1372. if (fjIsNull[curNode])
  1373. null_head[resind] = 'n';
  1374. else
  1375. {
  1376. null_head[resind] = ' ';
  1377. values[resind] = results[curNode];
  1378. }
  1379. }
  1380. }
  1381. }
  1382. /*
  1383.  * form the new result tuple (in the "normal" context)
  1384.  */
  1385. newTuple = (HeapTuple) heap_formtuple(targettype, values, null_head);
  1386. /*
  1387.  * free the nulls array if we allocated one..
  1388.  */
  1389. if (nodomains > 64)
  1390. {
  1391. pfree(null_head);
  1392. pfree(fjIsNull);
  1393. }
  1394. return newTuple;
  1395. }
  1396. /* ----------------------------------------------------------------
  1397.  * ExecProject
  1398.  *
  1399.  * projects a tuple based in projection info and stores
  1400.  * it in the specified tuple table slot.
  1401.  *
  1402.  * Note: someday soon the executor can be extended to eliminate
  1403.  *   redundant projections by storing pointers to datums
  1404.  *   in the tuple table and then passing these around when
  1405.  *   possible.  this should make things much quicker.
  1406.  *   -cim 6/3/91
  1407.  * ----------------------------------------------------------------
  1408.  */
  1409. TupleTableSlot *
  1410. ExecProject(ProjectionInfo *projInfo, bool *isDone)
  1411. {
  1412. TupleTableSlot *slot;
  1413. List    *targetlist;
  1414. int len;
  1415. TupleDesc tupType;
  1416. Datum    *tupValue;
  1417. ExprContext *econtext;
  1418. HeapTuple newTuple;
  1419. /*
  1420.  * sanity checks
  1421.  */
  1422. if (projInfo == NULL)
  1423. return (TupleTableSlot *) NULL;
  1424. /*
  1425.  * get the projection info we want
  1426.  */
  1427. slot = projInfo->pi_slot;
  1428. targetlist = projInfo->pi_targetlist;
  1429. len = projInfo->pi_len;
  1430. tupType = slot->ttc_tupleDescriptor;
  1431. tupValue = projInfo->pi_tupValue;
  1432. econtext = projInfo->pi_exprContext;
  1433. /*
  1434.  * form a new (result) tuple
  1435.  */
  1436. newTuple = ExecTargetList(targetlist,
  1437.   len,
  1438.   tupType,
  1439.   tupValue,
  1440.   econtext,
  1441.   isDone);
  1442. /*
  1443.  * store the tuple in the projection slot and return the slot.
  1444.  */
  1445. return (TupleTableSlot *)
  1446. ExecStoreTuple(newTuple,/* tuple to store */
  1447.    slot, /* slot to store in */
  1448.    InvalidBuffer, /* tuple has no buffer */
  1449.    true);
  1450. }