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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * execUtils.c
  4.  *   miscellanious executor utility routines
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.45 1999/05/25 16:08:39 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  * INTERFACE ROUTINES
  16.  * ExecAssignNodeBaseInfo
  17.  * ExecAssignDebugHooks  > preforms misc work done in all the
  18.  * ExecAssignExprContext / init node routines.
  19.  *
  20.  * ExecGetTypeInfo   |  old execCStructs interface
  21.  * ExecMakeTypeInfo   |  code from the version 1
  22.  * ExecOrderTypeInfo   |  lisp system.  These should
  23.  * ExecSetTypeInfo   |  go away or be updated soon.
  24.  * ExecFreeTypeInfo   |  -cim 11/1/89
  25.  * ExecTupleAttributes /
  26.  *
  27.  * QueryDescGetTypeInfo - moved here from main.c
  28.  * am not sure what uses it -cim 10/12/89
  29.  *
  30.  * ExecGetIndexKeyInfo
  31.  * ExecOpenIndices  | referenced by InitPlan, EndPlan,
  32.  * ExecCloseIndices  | ExecAppend, ExecReplace
  33.  * ExecFormIndexTuple  |
  34.  * ExecInsertIndexTuple /
  35.  *
  36.  *  NOTES
  37.  * This file has traditionally been the place to stick misc.
  38.  * executor support stuff that doesn't really go anyplace else.
  39.  *
  40.  */
  41. #include "postgres.h"
  42. #include "access/genam.h"
  43. #include "access/heapam.h"
  44. #include "access/itup.h"
  45. #include "catalog/catname.h"
  46. #include "catalog/index.h"
  47. #include "catalog/pg_type.h"
  48. #include "commands/command.h"
  49. #include "executor/execdebug.h"
  50. #include "executor/executor.h"
  51. #include "fmgr.h"
  52. #include "optimizer/clauses.h"
  53. #include "parser/parsetree.h"
  54. #include "utils/lsyscache.h"
  55. #include "utils/mcxt.h"
  56. static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
  57. AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
  58. /* ----------------------------------------------------------------
  59.  * global counters for number of tuples processed, retrieved,
  60.  * appended, replaced, deleted.
  61.  * ----------------------------------------------------------------
  62.  */
  63. int NTupleProcessed;
  64. int NTupleRetrieved;
  65. int NTupleReplaced;
  66. int NTupleAppended;
  67. int NTupleDeleted;
  68. int NIndexTupleInserted;
  69. extern int NIndexTupleProcessed; /* have to be defined in the
  70.  * access method level so that the
  71.  * cinterface.a will link ok. */
  72. /* ----------------------------------------------------------------
  73.  * statistic functions
  74.  * ----------------------------------------------------------------
  75.  */
  76. /* ----------------------------------------------------------------
  77.  * ResetTupleCount
  78.  * ----------------------------------------------------------------
  79.  */
  80. #ifdef NOT_USED
  81. void
  82. ResetTupleCount(void)
  83. {
  84. NTupleProcessed = 0;
  85. NTupleRetrieved = 0;
  86. NTupleAppended = 0;
  87. NTupleDeleted = 0;
  88. NTupleReplaced = 0;
  89. NIndexTupleProcessed = 0;
  90. }
  91. #endif
  92. /* ----------------------------------------------------------------
  93.  * PrintTupleCount
  94.  * ----------------------------------------------------------------
  95.  */
  96. #ifdef NOT_USED
  97. void
  98. DisplayTupleCount(FILE *statfp)
  99. {
  100. if (NTupleProcessed > 0)
  101. fprintf(statfp, "!t%d tuple%s processed, ", NTupleProcessed,
  102. (NTupleProcessed == 1) ? "" : "s");
  103. else
  104. {
  105. fprintf(statfp, "!tno tuples processed.n");
  106. return;
  107. }
  108. if (NIndexTupleProcessed > 0)
  109. fprintf(statfp, "%d indextuple%s processed, ", NIndexTupleProcessed,
  110. (NIndexTupleProcessed == 1) ? "" : "s");
  111. if (NIndexTupleInserted > 0)
  112. fprintf(statfp, "%d indextuple%s inserted, ", NIndexTupleInserted,
  113. (NIndexTupleInserted == 1) ? "" : "s");
  114. if (NTupleRetrieved > 0)
  115. fprintf(statfp, "%d tuple%s retrieved. ", NTupleRetrieved,
  116. (NTupleRetrieved == 1) ? "" : "s");
  117. if (NTupleAppended > 0)
  118. fprintf(statfp, "%d tuple%s appended. ", NTupleAppended,
  119. (NTupleAppended == 1) ? "" : "s");
  120. if (NTupleDeleted > 0)
  121. fprintf(statfp, "%d tuple%s deleted. ", NTupleDeleted,
  122. (NTupleDeleted == 1) ? "" : "s");
  123. if (NTupleReplaced > 0)
  124. fprintf(statfp, "%d tuple%s replaced. ", NTupleReplaced,
  125. (NTupleReplaced == 1) ? "" : "s");
  126. fprintf(statfp, "n");
  127. }
  128. #endif
  129. /* ----------------------------------------------------------------
  130.  *  miscellanious init node support functions
  131.  *
  132.  * ExecAssignNodeBaseInfo - assigns the baseid field of the node
  133.  * ExecAssignDebugHooks - assigns the node's debugging hooks
  134.  * ExecAssignExprContext - assigns the node's expression context
  135.  * ----------------------------------------------------------------
  136.  */
  137. /* ----------------
  138.  * ExecAssignNodeBaseInfo
  139.  *
  140.  * as it says, this assigns the baseid field of the node and
  141.  * increments the counter in the estate.  In addition, it initializes
  142.  * the base_parent field of the basenode.
  143.  * ----------------
  144.  */
  145. void
  146. ExecAssignNodeBaseInfo(EState *estate, CommonState *cstate, Plan *parent)
  147. {
  148. int baseId;
  149. baseId = estate->es_BaseId;
  150. cstate->cs_base_id = baseId;
  151. estate->es_BaseId = baseId + 1;
  152. }
  153. /* ----------------
  154.  * ExecAssignExprContext
  155.  *
  156.  * This initializes the ExprContext field.  It is only necessary
  157.  * to do this for nodes which use ExecQual or ExecTargetList
  158.  * because those routines depend on econtext. Other nodes which
  159.  * dont have to evaluate expressions don't need to do this.
  160.  * ----------------
  161.  */
  162. void
  163. ExecAssignExprContext(EState *estate, CommonState *commonstate)
  164. {
  165. ExprContext *econtext;
  166. econtext = makeNode(ExprContext);
  167. econtext->ecxt_scantuple = NULL; /* scan tuple slot */
  168. econtext->ecxt_innertuple = NULL; /* inner tuple slot */
  169. econtext->ecxt_outertuple = NULL; /* outer tuple slot */
  170. econtext->ecxt_relation = NULL; /* relation */
  171. econtext->ecxt_relid = 0; /* relid */
  172. econtext->ecxt_param_list_info = estate->es_param_list_info;
  173. econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
  174. econtext->ecxt_range_table = estate->es_range_table; /* range table */
  175. commonstate->cs_ExprContext = econtext;
  176. }
  177. /* ----------------------------------------------------------------
  178.  * Result slot tuple type and ProjectionInfo support
  179.  * ----------------------------------------------------------------
  180.  */
  181. /* ----------------
  182.  * ExecAssignResultType
  183.  * ----------------
  184.  */
  185. void
  186. ExecAssignResultType(CommonState *commonstate,
  187.  TupleDesc tupDesc)
  188. {
  189. TupleTableSlot *slot;
  190. slot = commonstate->cs_ResultTupleSlot;
  191. slot->ttc_tupleDescriptor = tupDesc;
  192. }
  193. /* ----------------
  194.  * ExecAssignResultTypeFromOuterPlan
  195.  * ----------------
  196.  */
  197. void
  198. ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
  199. {
  200. Plan    *outerPlan;
  201. TupleDesc tupDesc;
  202. outerPlan = outerPlan(node);
  203. tupDesc = ExecGetTupType(outerPlan);
  204. ExecAssignResultType(commonstate, tupDesc);
  205. }
  206. /* ----------------
  207.  * ExecAssignResultTypeFromTL
  208.  * ----------------
  209.  */
  210. void
  211. ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
  212. {
  213. List    *targetList;
  214. int i;
  215. int len;
  216. List    *tl;
  217. TargetEntry *tle;
  218. List    *fjtl;
  219. TupleDesc origTupDesc;
  220. targetList = node->targetlist;
  221. origTupDesc = ExecTypeFromTL(targetList);
  222. len = ExecTargetListLength(targetList);
  223. fjtl = NIL;
  224. tl = targetList;
  225. i = 0;
  226. while (tl != NIL || fjtl != NIL)
  227. {
  228. if (fjtl != NIL)
  229. {
  230. tle = lfirst(fjtl);
  231. fjtl = lnext(fjtl);
  232. }
  233. else
  234. {
  235. tle = lfirst(tl);
  236. tl = lnext(tl);
  237. }
  238. #ifdef SETS_FIXED
  239. if (!tl_is_resdom(tle))
  240. {
  241. Fjoin    *fj = (Fjoin *) lfirst(tle);
  242. /* it is a FJoin */
  243. fjtl = lnext(tle);
  244. tle = fj->fj_innerNode;
  245. }
  246. #endif
  247. i++;
  248. }
  249. if (len > 0)
  250. {
  251. ExecAssignResultType(commonstate,
  252.  origTupDesc);
  253. }
  254. else
  255. ExecAssignResultType(commonstate,
  256.  (TupleDesc) NULL);
  257. }
  258. /* ----------------
  259.  * ExecGetResultType
  260.  * ----------------
  261.  */
  262. TupleDesc
  263. ExecGetResultType(CommonState *commonstate)
  264. {
  265. TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
  266. return slot->ttc_tupleDescriptor;
  267. }
  268. /* ----------------
  269.  * ExecFreeResultType
  270.  * ----------------
  271.  */
  272. #ifdef NOT_USED
  273. void
  274. ExecFreeResultType(CommonState *commonstate)
  275. {
  276. TupleTableSlot *slot;
  277. TupleDesc tupType;
  278. slot = commonstate->cs_ResultTupleSlot;
  279. tupType = slot->ttc_tupleDescriptor;
  280. ExecFreeTypeInfo(tupType);
  281. }
  282. #endif
  283. /* ----------------
  284.  * ExecAssignProjectionInfo
  285.   forms the projection information from the node's targetlist
  286.  * ----------------
  287.  */
  288. void
  289. ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
  290. {
  291. ProjectionInfo *projInfo;
  292. List    *targetList;
  293. int len;
  294. targetList = node->targetlist;
  295. len = ExecTargetListLength(targetList);
  296. projInfo = makeNode(ProjectionInfo);
  297. projInfo->pi_targetlist = targetList;
  298. projInfo->pi_len = len;
  299. projInfo->pi_tupValue = (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len);
  300. projInfo->pi_exprContext = commonstate->cs_ExprContext;
  301. projInfo->pi_slot = commonstate->cs_ResultTupleSlot;
  302. commonstate->cs_ProjInfo = projInfo;
  303. }
  304. /* ----------------
  305.  * ExecFreeProjectionInfo
  306.  * ----------------
  307.  */
  308. void
  309. ExecFreeProjectionInfo(CommonState *commonstate)
  310. {
  311. ProjectionInfo *projInfo;
  312. /* ----------------
  313.  * get projection info.  if NULL then this node has
  314.  * none so we just return.
  315.  * ----------------
  316.  */
  317. projInfo = commonstate->cs_ProjInfo;
  318. if (projInfo == NULL)
  319. return;
  320. /* ----------------
  321.  * clean up memory used.
  322.  * ----------------
  323.  */
  324. if (projInfo->pi_tupValue != NULL)
  325. pfree(projInfo->pi_tupValue);
  326. pfree(projInfo);
  327. commonstate->cs_ProjInfo = NULL;
  328. }
  329. /* ----------------
  330.  * ExecFreeExprContext
  331.  * ----------------
  332.  */
  333. void
  334. ExecFreeExprContext(CommonState *commonstate)
  335. {
  336. ExprContext *econtext;
  337. /* ----------------
  338.  * get expression context.  if NULL then this node has
  339.  * none so we just return.
  340.  * ----------------
  341.  */
  342. econtext = commonstate->cs_ExprContext;
  343. if (econtext == NULL)
  344. return;
  345. /* ----------------
  346.  * clean up memory used.
  347.  * ----------------
  348.  */
  349. pfree(econtext);
  350. commonstate->cs_ExprContext = NULL;
  351. }
  352. /* ----------------
  353.  * ExecFreeTypeInfo
  354.  * ----------------
  355.  */
  356. void
  357. ExecFreeTypeInfo(CommonState *commonstate)
  358. {
  359. TupleDesc tupDesc;
  360. tupDesc = commonstate->cs_ResultTupleSlot->ttc_tupleDescriptor;
  361. if (tupDesc == NULL)
  362. return;
  363. /* ----------------
  364.  * clean up memory used.
  365.  * ----------------
  366.  */
  367. FreeTupleDesc(tupDesc);
  368. commonstate->cs_ResultTupleSlot->ttc_tupleDescriptor = NULL;
  369. }
  370. /* ----------------------------------------------------------------
  371.  * the following scan type support functions are for
  372.  * those nodes which are stubborn and return tuples in
  373.  * their Scan tuple slot instead of their Result tuple
  374.  * slot.. luck fur us, these nodes do not do projections
  375.  * so we don't have to worry about getting the ProjectionInfo
  376.  * right for them...  -cim 6/3/91
  377.  * ----------------------------------------------------------------
  378.  */
  379. /* ----------------
  380.  * ExecGetScanType
  381.  * ----------------
  382.  */
  383. TupleDesc
  384. ExecGetScanType(CommonScanState *csstate)
  385. {
  386. TupleTableSlot *slot = csstate->css_ScanTupleSlot;
  387. return slot->ttc_tupleDescriptor;
  388. }
  389. /* ----------------
  390.  * ExecFreeScanType
  391.  * ----------------
  392.  */
  393. #ifdef NOT_USED
  394. void
  395. ExecFreeScanType(CommonScanState *csstate)
  396. {
  397. TupleTableSlot *slot;
  398. TupleDesc tupType;
  399. slot = csstate->css_ScanTupleSlot;
  400. tupType = slot->ttc_tupleDescriptor;
  401. ExecFreeTypeInfo(tupType);
  402. }
  403. #endif
  404. /* ----------------
  405.  * ExecAssignScanType
  406.  * ----------------
  407.  */
  408. void
  409. ExecAssignScanType(CommonScanState *csstate,
  410.    TupleDesc tupDesc)
  411. {
  412. TupleTableSlot *slot;
  413. slot = (TupleTableSlot *) csstate->css_ScanTupleSlot;
  414. slot->ttc_tupleDescriptor = tupDesc;
  415. }
  416. /* ----------------
  417.  * ExecAssignScanTypeFromOuterPlan
  418.  * ----------------
  419.  */
  420. void
  421. ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate)
  422. {
  423. Plan    *outerPlan;
  424. TupleDesc tupDesc;
  425. outerPlan = outerPlan(node);
  426. tupDesc = ExecGetTupType(outerPlan);
  427. ExecAssignScanType(csstate, tupDesc);
  428. }
  429. /* ----------------------------------------------------------------
  430.  * ExecTypeFromTL support routines.
  431.  *
  432.  * these routines are used mainly from ExecTypeFromTL.
  433.  * -cim 6/12/90
  434.  *
  435.  * old comments
  436.  * Routines dealing with the structure 'attribute' which conatains
  437.  * the type information about attributes in a tuple:
  438.  *
  439.  * ExecMakeTypeInfo(noType)
  440.  * returns pointer to array of 'noType' structure 'attribute'.
  441.  * ExecSetTypeInfo(index, typeInfo, attNum, attLen)
  442.  * sets the element indexed by 'index' in typeInfo with
  443.  * the values: attNum, attLen.
  444.  * ExecFreeTypeInfo(typeInfo)
  445.  * frees the structure 'typeInfo'.
  446.  * ----------------------------------------------------------------
  447.  */
  448. /* ----------------
  449.  * ExecSetTypeInfo
  450.  *
  451.  * This initializes fields of a single attribute in a
  452.  * tuple descriptor from the specified parameters.
  453.  *
  454.  * XXX this duplicates much of the functionality of TupleDescInitEntry.
  455.  * the routines should be moved to the same place and be rewritten
  456.  * to share common code.
  457.  * ----------------
  458.  */
  459. #ifdef NOT_USED
  460. void
  461. ExecSetTypeInfo(int index,
  462. TupleDesc typeInfo,
  463. Oid typeID,
  464. int attNum,
  465. int attLen,
  466. char *attName,
  467. bool attbyVal,
  468. char attalign)
  469. {
  470. Form_pg_attribute att;
  471. /* ----------------
  472.  * get attribute pointer and preform a sanity check..
  473.  * ----------------
  474.  */
  475. att = typeInfo[index];
  476. if (att == NULL)
  477. elog(ERROR, "ExecSetTypeInfo: trying to assign through NULL");
  478. /* ----------------
  479.  * assign values to the tuple descriptor, being careful not
  480.  * to copy a null attName..
  481.  *
  482.  * XXX it is unknown exactly what information is needed to
  483.  * initialize the attribute struct correctly so for now
  484.  * we use 0.  this should be fixed -- otherwise we run the
  485.  * risk of using garbage data. -cim 5/5/91
  486.  * ----------------
  487.  */
  488. att->attrelid = 0; /* dummy value */
  489. if (attName != (char *) NULL)
  490. StrNCpy(att->attname.data, attName, NAMEDATALEN);
  491. else
  492. MemSet(att->attname.data, 0, NAMEDATALEN);
  493. att->atttypid = typeID;
  494. att->attdefrel = 0; /* dummy value */
  495. att->attdisbursion = 0; /* dummy value */
  496. att->atttyparg = 0; /* dummy value */
  497. att->attlen = attLen;
  498. att->attnum = attNum;
  499. att->attbound = 0; /* dummy value */
  500. att->attbyval = attbyVal;
  501. att->attcanindex = 0; /* dummy value */
  502. att->attproc = 0; /* dummy value */
  503. att->attnelems = 0; /* dummy value */
  504. att->attcacheoff = -1;
  505. att->atttypmod = -1;
  506. att->attisset = false;
  507. att->attalign = attalign;
  508. }
  509. /* ----------------
  510.  * ExecFreeTypeInfo frees the array of attrbutes
  511.  * created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
  512.  * ----------------
  513.  */
  514. void
  515. ExecFreeTypeInfo(TupleDesc typeInfo)
  516. {
  517. /* ----------------
  518.  * do nothing if asked to free a null pointer
  519.  * ----------------
  520.  */
  521. if (typeInfo == NULL)
  522. return;
  523. /* ----------------
  524.  * the entire array of typeinfo pointers created by
  525.  * ExecMakeTypeInfo was allocated with a single palloc()
  526.  * so we can deallocate the whole array with a single pfree().
  527.  * (we should not try and free all the elements in the array)
  528.  * -cim 6/12/90
  529.  * ----------------
  530.  */
  531. pfree(typeInfo);
  532. }
  533. /* ----------------------------------------------------------------
  534.  * QueryDescGetTypeInfo
  535.  *
  536.  *| I don't know how this is used, all I know is that it
  537.  *| appeared one day in main.c so I moved it here. -cim 11/1/89
  538.  * ----------------------------------------------------------------
  539.  */
  540. TupleDesc
  541. QueryDescGetTypeInfo(QueryDesc *queryDesc)
  542. {
  543. Plan    *plan;
  544. TupleDesc tupleType;
  545. List    *targetList;
  546. AttrInfo   *attinfo = (AttrInfo *) palloc(sizeof(AttrInfo));
  547. plan = queryDesc->plantree;
  548. tupleType = (TupleDesc) ExecGetTupType(plan);
  549. /*
  550. targetList =  plan->targetlist;
  551. attinfo->numAttr = ExecTargetListLength(targetList);
  552. attinfo->attrs = tupleType;
  553. */
  554. attinfo->numAttr = tupleType->natts;
  555. attinfo->attrs = tupleType->attrs;
  556. return attinfo;
  557. }
  558. #endif
  559. /* ----------------------------------------------------------------
  560.  *   ExecInsertIndexTuples support
  561.  * ----------------------------------------------------------------
  562.  */
  563. /* ----------------------------------------------------------------
  564.  * ExecGetIndexKeyInfo
  565.  *
  566.  * Extracts the index key attribute numbers from
  567.  * an index tuple form (i.e. a tuple from the pg_index relation)
  568.  * into an array of attribute numbers.  The array and the
  569.  * size of the array are returned to the caller via return
  570.  * parameters.
  571.  * ----------------------------------------------------------------
  572.  */
  573. static void
  574. ExecGetIndexKeyInfo(Form_pg_index indexTuple,
  575. int *numAttsOutP,
  576. AttrNumber **attsOutP,
  577. FuncIndexInfoPtr fInfoP)
  578. {
  579. int i;
  580. int numKeys;
  581. AttrNumber *attKeys;
  582. /* ----------------
  583.  * check parameters
  584.  * ----------------
  585.  */
  586. if (numAttsOutP == NULL && attsOutP == NULL)
  587. {
  588. elog(DEBUG, "ExecGetIndexKeyInfo: %s",
  589. "invalid parameters: numAttsOutP and attsOutP must be non-NULL");
  590. }
  591. /* ----------------
  592.  * set the procid for a possible functional index.
  593.  * ----------------
  594.  */
  595. FIsetProcOid(fInfoP, indexTuple->indproc);
  596. /* ----------------
  597.  * count the number of keys..
  598.  * ----------------
  599.  */
  600. numKeys = 0;
  601. for (i = 0; i < INDEX_MAX_KEYS &&
  602.  indexTuple->indkey[i] != InvalidAttrNumber; i++)
  603. numKeys++;
  604. /* ----------------
  605.  * place number keys in callers return area
  606.  * or the number of arguments for a functional index.
  607.  *
  608.  * If we have a functional index then the number of
  609.  * attributes defined in the index must 1 (the function's
  610.  * single return value).
  611.  * ----------------
  612.  */
  613. if (FIgetProcOid(fInfoP) != InvalidOid)
  614. {
  615. FIsetnArgs(fInfoP, numKeys);
  616. (*numAttsOutP) = 1;
  617. }
  618. else
  619. (*numAttsOutP) = numKeys;
  620. if (numKeys < 1)
  621. {
  622. elog(DEBUG, "ExecGetIndexKeyInfo: %s",
  623.  "all index key attribute numbers are zero!");
  624. (*attsOutP) = NULL;
  625. return;
  626. }
  627. /* ----------------
  628.  * allocate and fill in array of key attribute numbers
  629.  * ----------------
  630.  */
  631. CXT1_printf("ExecGetIndexKeyInfo: context is %dn", CurrentMemoryContext);
  632. attKeys = (AttrNumber *) palloc(numKeys * sizeof(AttrNumber));
  633. for (i = 0; i < numKeys; i++)
  634. attKeys[i] = indexTuple->indkey[i];
  635. /* ----------------
  636.  * return array to caller.
  637.  * ----------------
  638.  */
  639. (*attsOutP) = attKeys;
  640. }
  641. /* ----------------------------------------------------------------
  642.  * ExecOpenIndices
  643.  *
  644.  * Here we scan the pg_index relation to find indices
  645.  * associated with a given heap relation oid. Since we
  646.  * don't know in advance how many indices we have, we
  647.  * form lists containing the information we need from
  648.  * pg_index and then process these lists.
  649.  *
  650.  * Note: much of this code duplicates effort done by
  651.  * the IndexCatalogInformation function in plancat.c
  652.  * because IndexCatalogInformation is poorly written.
  653.  *
  654.  * It would be much better if the functionality provided
  655.  * by this function and IndexCatalogInformation was
  656.  * in the form of a small set of orthogonal routines..
  657.  * If you are trying to understand this, I suggest you
  658.  * look at the code to IndexCatalogInformation and
  659.  * FormIndexTuple.. -cim 9/27/89
  660.  * ----------------------------------------------------------------
  661.  */
  662. void
  663. ExecOpenIndices(Oid resultRelationOid,
  664. RelationInfo *resultRelationInfo)
  665. {
  666. Relation indexRd;
  667. HeapScanDesc indexSd;
  668. ScanKeyData key;
  669. HeapTuple tuple;
  670. Form_pg_index indexStruct;
  671. Oid indexOid;
  672. List    *oidList;
  673. List    *nkeyList;
  674. List    *keyList;
  675. List    *fiList;
  676. char    *predString;
  677. List    *predList;
  678. List    *indexoid;
  679. List    *numkeys;
  680. List    *indexkeys;
  681. List    *indexfuncs;
  682. List    *indexpreds;
  683. int len;
  684. RelationPtr relationDescs;
  685. IndexInfo **indexInfoArray;
  686. FuncIndexInfoPtr fInfoP;
  687. int numKeyAtts;
  688. AttrNumber *indexKeyAtts;
  689. PredInfo   *predicate;
  690. int i;
  691. /* ----------------
  692.  * open pg_index
  693.  * ----------------
  694.  */
  695. indexRd = heap_openr(IndexRelationName);
  696. /* ----------------
  697.  * form a scan key
  698.  * ----------------
  699.  */
  700. ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
  701.    F_OIDEQ,
  702.    ObjectIdGetDatum(resultRelationOid));
  703. /* ----------------
  704.  * scan the index relation, looking for indices for our
  705.  * result relation..
  706.  * ----------------
  707.  */
  708. indexSd = heap_beginscan(indexRd, /* scan desc */
  709.  false, /* scan backward flag */
  710.  SnapshotNow, /* NOW snapshot */
  711.  1, /* number scan keys */
  712.  &key); /* scan keys */
  713. oidList = NIL;
  714. nkeyList = NIL;
  715. keyList = NIL;
  716. fiList = NIL;
  717. predList = NIL;
  718. while (HeapTupleIsValid(tuple = heap_getnext(indexSd, 0)))
  719. {
  720. /* ----------------
  721.  * For each index relation we find, extract the information
  722.  * we need and store it in a list..
  723.  *
  724.  * first get the oid of the index relation from the tuple
  725.  * ----------------
  726.  */
  727. indexStruct = (Form_pg_index) GETSTRUCT(tuple);
  728. indexOid = indexStruct->indexrelid;
  729. /* ----------------
  730.  * allocate space for functional index information.
  731.  * ----------------
  732.  */
  733. fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP));
  734. /* ----------------
  735.  * next get the index key information from the tuple
  736.  * ----------------
  737.  */
  738. ExecGetIndexKeyInfo(indexStruct,
  739. &numKeyAtts,
  740. &indexKeyAtts,
  741. fInfoP);
  742. /* ----------------
  743.  * next get the index predicate from the tuple
  744.  * ----------------
  745.  */
  746. if (VARSIZE(&indexStruct->indpred) != 0)
  747. {
  748. predString = fmgr(F_TEXTOUT, &indexStruct->indpred);
  749. predicate = (PredInfo *) stringToNode(predString);
  750. pfree(predString);
  751. }
  752. else
  753. predicate = NULL;
  754. /* ----------------
  755.  * save the index information into lists
  756.  * ----------------
  757.  */
  758. oidList = lconsi(indexOid, oidList);
  759. nkeyList = lconsi(numKeyAtts, nkeyList);
  760. keyList = lcons(indexKeyAtts, keyList);
  761. fiList = lcons(fInfoP, fiList);
  762. predList = lcons(predicate, predList);
  763. }
  764. /* ----------------
  765.  * we have the info we need so close the pg_index relation..
  766.  * ----------------
  767.  */
  768. heap_endscan(indexSd);
  769. heap_close(indexRd);
  770. /* ----------------
  771.  * Now that we've collected the index information into three
  772.  * lists, we open the index relations and store the descriptors
  773.  * and the key information into arrays.
  774.  * ----------------
  775.  */
  776. len = length(oidList);
  777. if (len > 0)
  778. {
  779. /* ----------------
  780.  *  allocate space for relation descs
  781.  * ----------------
  782.  */
  783. CXT1_printf("ExecOpenIndices: context is %dn", CurrentMemoryContext);
  784. relationDescs = (RelationPtr)
  785. palloc(len * sizeof(Relation));
  786. /* ----------------
  787.  *  initialize index info array
  788.  * ----------------
  789.  */
  790. CXT1_printf("ExecOpenIndices: context is %dn", CurrentMemoryContext);
  791. indexInfoArray = (IndexInfo **)
  792. palloc(len * sizeof(IndexInfo *));
  793. for (i = 0; i < len; i++)
  794. {
  795. IndexInfo  *ii = makeNode(IndexInfo);
  796. ii->ii_NumKeyAttributes = 0;
  797. ii->ii_KeyAttributeNumbers = (AttrNumber *) NULL;
  798. ii->ii_FuncIndexInfo = (FuncIndexInfoPtr) NULL;
  799. ii->ii_Predicate = NULL;
  800. indexInfoArray[i] = ii;
  801. }
  802. /* ----------------
  803.  *  attempt to open each of the indices.  If we succeed,
  804.  *  then store the index relation descriptor into the
  805.  *  relation descriptor array.
  806.  * ----------------
  807.  */
  808. i = 0;
  809. foreach(indexoid, oidList)
  810. {
  811. Relation indexDesc;
  812. indexOid = lfirsti(indexoid);
  813. indexDesc = index_open(indexOid);
  814. if (indexDesc != NULL)
  815. {
  816. relationDescs[i++] = indexDesc;
  817. /*
  818.  * Hack for not btree and hash indices: they use relation
  819.  * level exclusive locking on updation (i.e. - they are
  820.  * not ready for MVCC) and so we have to exclusively lock
  821.  * indices here to prevent deadlocks if we will scan them
  822.  * - index_beginscan places AccessShareLock, indices
  823.  * update methods don't use locks at all. We release this
  824.  * lock in ExecCloseIndices. Note, that hashes use page
  825.  * level locking - i.e. are not deadlock-free, - let's
  826.  * them be on their way -:)) vadim 03-12-1998
  827.  */
  828. if (indexDesc->rd_rel->relam != BTREE_AM_OID &&
  829. indexDesc->rd_rel->relam != HASH_AM_OID)
  830. LockRelation(indexDesc, AccessExclusiveLock);
  831. }
  832. }
  833. /* ----------------
  834.  *  store the relation descriptor array and number of
  835.  *  descs into the result relation info.
  836.  * ----------------
  837.  */
  838. resultRelationInfo->ri_NumIndices = i;
  839. resultRelationInfo->ri_IndexRelationDescs = relationDescs;
  840. /* ----------------
  841.  *  store the index key information collected in our
  842.  *  lists into the index info array
  843.  * ----------------
  844.  */
  845. i = 0;
  846. foreach(numkeys, nkeyList)
  847. {
  848. numKeyAtts = lfirsti(numkeys);
  849. indexInfoArray[i++]->ii_NumKeyAttributes = numKeyAtts;
  850. }
  851. i = 0;
  852. foreach(indexkeys, keyList)
  853. {
  854. indexKeyAtts = (AttrNumber *) lfirst(indexkeys);
  855. indexInfoArray[i++]->ii_KeyAttributeNumbers = indexKeyAtts;
  856. }
  857. i = 0;
  858. foreach(indexfuncs, fiList)
  859. {
  860. FuncIndexInfoPtr fiP = (FuncIndexInfoPtr) lfirst(indexfuncs);
  861. indexInfoArray[i++]->ii_FuncIndexInfo = fiP;
  862. }
  863. i = 0;
  864. foreach(indexpreds, predList)
  865. indexInfoArray[i++]->ii_Predicate = lfirst(indexpreds);
  866. /* ----------------
  867.  *  store the index info array into relation info
  868.  * ----------------
  869.  */
  870. resultRelationInfo->ri_IndexRelationInfo = indexInfoArray;
  871. }
  872. /* ----------------
  873.  * All done,  resultRelationInfo now contains complete information
  874.  * on the indices associated with the result relation.
  875.  * ----------------
  876.  */
  877. /* should free oidList, nkeyList and keyList here */
  878. /* OK - let's do it   -jolly */
  879. freeList(oidList);
  880. freeList(nkeyList);
  881. freeList(keyList);
  882. freeList(fiList);
  883. freeList(predList);
  884. }
  885. /* ----------------------------------------------------------------
  886.  * ExecCloseIndices
  887.  *
  888.  * Close the index relations stored in resultRelationInfo
  889.  * ----------------------------------------------------------------
  890.  */
  891. void
  892. ExecCloseIndices(RelationInfo *resultRelationInfo)
  893. {
  894. int i;
  895. int numIndices;
  896. RelationPtr relationDescs;
  897. numIndices = resultRelationInfo->ri_NumIndices;
  898. relationDescs = resultRelationInfo->ri_IndexRelationDescs;
  899. for (i = 0; i < numIndices; i++)
  900. {
  901. if (relationDescs[i] == NULL)
  902. continue;
  903. /*
  904.  * Notes in ExecOpenIndices.
  905.  */
  906. if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID &&
  907. relationDescs[i]->rd_rel->relam != HASH_AM_OID)
  908. UnlockRelation(relationDescs[i], AccessExclusiveLock);
  909. index_close(relationDescs[i]);
  910. }
  911. /*
  912.  * XXX should free indexInfo array here too.
  913.  */
  914. }
  915. /* ----------------------------------------------------------------
  916.  * ExecFormIndexTuple
  917.  *
  918.  * Most of this code is cannabilized from DefaultBuild().
  919.  * As said in the comments for ExecOpenIndices, most of
  920.  * this functionality should be rearranged into a proper
  921.  * set of routines..
  922.  * ----------------------------------------------------------------
  923.  */
  924. #ifdef NOT_USED
  925. IndexTuple
  926. ExecFormIndexTuple(HeapTuple heapTuple,
  927.    Relation heapRelation,
  928.    Relation indexRelation,
  929.    IndexInfo *indexInfo)
  930. {
  931. IndexTuple indexTuple;
  932. TupleDesc heapDescriptor;
  933. TupleDesc indexDescriptor;
  934. Datum    *datum;
  935. char    *nulls;
  936. int numberOfAttributes;
  937. AttrNumber *keyAttributeNumbers;
  938. FuncIndexInfoPtr fInfoP;
  939. /* ----------------
  940.  * get information from index info structure
  941.  * ----------------
  942.  */
  943. numberOfAttributes = indexInfo->ii_NumKeyAttributes;
  944. keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers;
  945. fInfoP = indexInfo->ii_FuncIndexInfo;
  946. /* ----------------
  947.  * datum and null are arrays in which we collect the index attributes
  948.  * when forming a new index tuple.
  949.  * ----------------
  950.  */
  951. CXT1_printf("ExecFormIndexTuple: context is %dn", CurrentMemoryContext);
  952. datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
  953. nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
  954. /* ----------------
  955.  * get the tuple descriptors from the relations so we know
  956.  * how to form the index tuples..
  957.  * ----------------
  958.  */
  959. heapDescriptor = RelationGetDescr(heapRelation);
  960. indexDescriptor = RelationGetDescr(indexRelation);
  961. /* ----------------
  962.  * FormIndexDatum fills in its datum and null parameters
  963.  * with attribute information taken from the given heap tuple.
  964.  * ----------------
  965.  */
  966. FormIndexDatum(numberOfAttributes, /* num attributes */
  967.    keyAttributeNumbers, /* array of att nums to extract */
  968.    heapTuple, /* tuple from base relation */
  969.    heapDescriptor, /* heap tuple's descriptor */
  970.    datum, /* return: array of attributes */
  971.    nulls, /* return: array of char's */
  972.    fInfoP); /* functional index information */
  973. indexTuple = index_formtuple(indexDescriptor,
  974.  datum,
  975.  nulls);
  976. /* ----------------
  977.  * free temporary arrays
  978.  *
  979.  * XXX should store these in the IndexInfo instead of allocating
  980.  *    and freeing on every insertion, but efficency here is not
  981.  *    that important and FormIndexTuple is wasteful anyways..
  982.  *    -cim 9/27/89
  983.  * ----------------
  984.  */
  985. pfree(nulls);
  986. pfree(datum);
  987. return indexTuple;
  988. }
  989. #endif
  990. /* ----------------------------------------------------------------
  991.  * ExecInsertIndexTuples
  992.  *
  993.  * This routine takes care of inserting index tuples
  994.  * into all the relations indexing the result relation
  995.  * when a heap tuple is inserted into the result relation.
  996.  * Much of this code should be moved into the genam
  997.  * stuff as it only exists here because the genam stuff
  998.  * doesn't provide the functionality needed by the
  999.  * executor.. -cim 9/27/89
  1000.  * ----------------------------------------------------------------
  1001.  */
  1002. void
  1003. ExecInsertIndexTuples(TupleTableSlot *slot,
  1004.   ItemPointer tupleid,
  1005.   EState *estate,
  1006.   bool is_update)
  1007. {
  1008. HeapTuple heapTuple;
  1009. RelationInfo *resultRelationInfo;
  1010. int i;
  1011. int numIndices;
  1012. RelationPtr relationDescs;
  1013. Relation heapRelation;
  1014. IndexInfo **indexInfoArray;
  1015. IndexInfo  *indexInfo;
  1016. Node    *predicate;
  1017. bool satisfied;
  1018. ExprContext *econtext;
  1019. InsertIndexResult result;
  1020. int numberOfAttributes;
  1021. AttrNumber *keyAttributeNumbers;
  1022. FuncIndexInfoPtr fInfoP;
  1023. TupleDesc heapDescriptor;
  1024. Datum    *datum;
  1025. char    *nulls;
  1026. heapTuple = slot->val;
  1027. /* ----------------
  1028.  * get information from the result relation info structure.
  1029.  * ----------------
  1030.  */
  1031. resultRelationInfo = estate->es_result_relation_info;
  1032. numIndices = resultRelationInfo->ri_NumIndices;
  1033. relationDescs = resultRelationInfo->ri_IndexRelationDescs;
  1034. indexInfoArray = resultRelationInfo->ri_IndexRelationInfo;
  1035. heapRelation = resultRelationInfo->ri_RelationDesc;
  1036. /* ----------------
  1037.  * for each index, form and insert the index tuple
  1038.  * ----------------
  1039.  */
  1040. econtext = NULL;
  1041. for (i = 0; i < numIndices; i++)
  1042. {
  1043. if (relationDescs[i] == NULL)
  1044. continue;
  1045. indexInfo = indexInfoArray[i];
  1046. predicate = indexInfo->ii_Predicate;
  1047. if (predicate != NULL)
  1048. {
  1049. if (econtext == NULL)
  1050. econtext = makeNode(ExprContext);
  1051. econtext->ecxt_scantuple = slot;
  1052. /* Skip this index-update if the predicate isn't satisfied */
  1053. satisfied = ExecQual((List *) predicate, econtext);
  1054. if (satisfied == false)
  1055. continue;
  1056. }
  1057. /* ----------------
  1058.  * get information from index info structure
  1059.  * ----------------
  1060.  */
  1061. numberOfAttributes = indexInfo->ii_NumKeyAttributes;
  1062. keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers;
  1063. fInfoP = indexInfo->ii_FuncIndexInfo;
  1064. datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
  1065. nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
  1066. heapDescriptor = (TupleDesc) RelationGetDescr(heapRelation);
  1067. FormIndexDatum(numberOfAttributes, /* num attributes */
  1068.    keyAttributeNumbers, /* array of att nums to
  1069.  * extract */
  1070.    heapTuple, /* tuple from base relation */
  1071.    heapDescriptor, /* heap tuple's descriptor */
  1072.    datum, /* return: array of attributes */
  1073.    nulls, /* return: array of char's */
  1074.    fInfoP); /* functional index information */
  1075. result = index_insert(relationDescs[i], /* index relation */
  1076.   datum, /* array of heaptuple Datums */
  1077.   nulls, /* info on nulls */
  1078.   &(heapTuple->t_self), /* tid of heap tuple */
  1079.   heapRelation);
  1080. /* ----------------
  1081.  * keep track of index inserts for debugging
  1082.  * ----------------
  1083.  */
  1084. IncrIndexInserted();
  1085. /* ----------------
  1086.  * free index tuple after insertion
  1087.  * ----------------
  1088.  */
  1089. if (result)
  1090. pfree(result);
  1091. }
  1092. if (econtext != NULL)
  1093. pfree(econtext);
  1094. }
  1095. void
  1096. SetChangedParamList(Plan *node, List *newchg)
  1097. {
  1098. List    *nl;
  1099. foreach(nl, newchg)
  1100. {
  1101. int paramId = lfirsti(nl);
  1102. /* if this node doesn't depend on a param ... */
  1103. if (!intMember(paramId, node->extParam) &&
  1104. !intMember(paramId, node->locParam))
  1105. continue;
  1106. /* if this param is already in list of changed ones ... */
  1107. if (intMember(paramId, node->chgParam))
  1108. continue;
  1109. /* else - add this param to the list */
  1110. node->chgParam = lappendi(node->chgParam, paramId);
  1111. }
  1112. }