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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * execMain.c
  4.  *   top level executor interface routines
  5.  *
  6.  * INTERFACE ROUTINES
  7.  * ExecutorStart()
  8.  * ExecutorRun()
  9.  * ExecutorEnd()
  10.  *
  11.  * The old ExecutorMain() has been replaced by ExecutorStart(),
  12.  * ExecutorRun() and ExecutorEnd()
  13.  *
  14.  * These three procedures are the external interfaces to the executor.
  15.  * In each case, the query descriptor and the execution state is required
  16.  *  as arguments
  17.  *
  18.  * ExecutorStart() must be called at the beginning of any execution of any
  19.  * query plan and ExecutorEnd() should always be called at the end of
  20.  * execution of a plan.
  21.  *
  22.  * ExecutorRun accepts 'feature' and 'count' arguments that specify whether
  23.  * the plan is to be executed forwards, backwards, and for how many tuples.
  24.  *
  25.  * Copyright (c) 1994, Regents of the University of California
  26.  *
  27.  *
  28.  * IDENTIFICATION
  29.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/execMain.c,v 1.88 1999/06/17 15:15:49 momjian Exp $
  30.  *
  31.  *-------------------------------------------------------------------------
  32.  */
  33. #include <string.h>
  34. #include "postgres.h"
  35. #include "miscadmin.h"
  36. #include "executor/executor.h"
  37. #include "executor/execdefs.h"
  38. #include "executor/execdebug.h"
  39. #include "executor/nodeIndexscan.h"
  40. #include "utils/builtins.h"
  41. #include "utils/palloc.h"
  42. #include "utils/acl.h"
  43. #include "utils/syscache.h"
  44. #include "utils/tqual.h"
  45. #include "parser/parsetree.h" /* rt_fetch() */
  46. #include "storage/bufmgr.h"
  47. #include "storage/lmgr.h"
  48. #include "storage/smgr.h"
  49. #include "commands/async.h"
  50. /* #include "access/localam.h" */
  51. #include "optimizer/var.h"
  52. #include "access/heapam.h"
  53. #include "access/xact.h"
  54. #include "catalog/heap.h"
  55. #include "commands/trigger.h"
  56. void ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
  57.    Query *parseTree);
  58. /* decls for local routines only used within this module */
  59. static TupleDesc InitPlan(CmdType operation,
  60.  Query *parseTree,
  61.  Plan *plan,
  62.  EState *estate);
  63. static void EndPlan(Plan *plan,
  64. EState *estate);
  65. static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
  66. CmdType operation,
  67. int offsetTuples,
  68. int numberTuples,
  69. ScanDirection direction,
  70. DestReceiver *destfunc);
  71. static void ExecRetrieve(TupleTableSlot *slot,
  72.  DestReceiver *destfunc,
  73.  EState *estate);
  74. static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
  75.    EState *estate);
  76. static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
  77.    EState *estate);
  78. static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
  79. EState *estate);
  80. TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
  81. static TupleTableSlot *EvalPlanQualNext(EState *estate);
  82. /* end of local decls */
  83. /* ----------------------------------------------------------------
  84.  * ExecutorStart
  85.  *
  86.  * This routine must be called at the beginning of any execution of any
  87.  * query plan
  88.  *
  89.  * returns (AttrInfo*) which describes the attributes of the tuples to
  90.  * be returned by the query.
  91.  *
  92.  * ----------------------------------------------------------------
  93.  */
  94. TupleDesc
  95. ExecutorStart(QueryDesc *queryDesc, EState *estate)
  96. {
  97. TupleDesc result;
  98. /* sanity checks */
  99. Assert(queryDesc != NULL);
  100. if (queryDesc->plantree->nParamExec > 0)
  101. {
  102. estate->es_param_exec_vals = (ParamExecData *)
  103. palloc(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
  104. memset(estate->es_param_exec_vals, 0, queryDesc->plantree->nParamExec * sizeof(ParamExecData));
  105. }
  106. /*
  107.  * Make our own private copy of the current queries snapshot data
  108.  */
  109. if (QuerySnapshot == NULL)
  110. estate->es_snapshot = NULL;
  111. else
  112. {
  113. estate->es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
  114. memcpy(estate->es_snapshot, QuerySnapshot, sizeof(SnapshotData));
  115. if (estate->es_snapshot->xcnt > 0)
  116. {
  117. estate->es_snapshot->xip = (TransactionId *)
  118. palloc(estate->es_snapshot->xcnt * sizeof(TransactionId));
  119. memcpy(estate->es_snapshot->xip, QuerySnapshot->xip,
  120.    estate->es_snapshot->xcnt * sizeof(TransactionId));
  121. }
  122. }
  123. /*
  124.  * Initialize the plan
  125.  */
  126. result = InitPlan(queryDesc->operation,
  127.   queryDesc->parsetree,
  128.   queryDesc->plantree,
  129.   estate);
  130. /*
  131.  * reset buffer refcount.  the current refcounts are saved and will be
  132.  * restored when ExecutorEnd is called
  133.  *
  134.  * this makes sure that when ExecutorRun's are called recursively as for
  135.  * postquel functions, the buffers pinned by one ExecutorRun will not
  136.  * be unpinned by another ExecutorRun.
  137.  */
  138. BufferRefCountReset(estate->es_refcount);
  139. return result;
  140. }
  141. /* ----------------------------------------------------------------
  142.  * ExecutorRun
  143.  *
  144.  * This is the main routine of the executor module. It accepts
  145.  * the query descriptor from the traffic cop and executes the
  146.  * query plan.
  147.  *
  148.  * ExecutorStart must have been called already.
  149.  *
  150.  * the different features supported are:
  151.  *  EXEC_RUN: retrieve all tuples in the forward direction
  152.  *  EXEC_FOR: retrieve 'count' number of tuples in the forward dir
  153.  *  EXEC_BACK: retrieve 'count' number of tuples in the backward dir
  154.  *  EXEC_RETONE: return one tuple but don't 'retrieve' it
  155.  *    used in postquel function processing
  156.  *
  157.  *
  158.  * ----------------------------------------------------------------
  159.  */
  160. TupleTableSlot *
  161. ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature,
  162. Node *limoffset, Node *limcount)
  163. {
  164. CmdType operation;
  165. Plan    *plan;
  166. TupleTableSlot *result;
  167. CommandDest dest;
  168. DestReceiver *destfunc;
  169. int offset = 0;
  170. int count = 0;
  171. /*
  172.  * sanity checks
  173.  */
  174. Assert(queryDesc != NULL);
  175. /*
  176.  * extract information from the query descriptor and the query
  177.  * feature.
  178.  */
  179. operation = queryDesc->operation;
  180. plan = queryDesc->plantree;
  181. dest = queryDesc->dest;
  182. destfunc = DestToFunction(dest);
  183. estate->es_processed = 0;
  184. estate->es_lastoid = InvalidOid;
  185. /*
  186.  * FIXME: the dest setup function ought to be handed the tuple desc
  187.  * for the tuples to be output, but I'm not quite sure how to get that
  188.  * info at this point. For now, passing NULL is OK because no
  189.  * existing dest setup function actually uses the pointer.
  190.  */
  191. (*destfunc->setup) (destfunc, (TupleDesc) NULL);
  192. /*
  193.  * if given get the offset of the LIMIT clause
  194.  */
  195. if (limoffset != NULL)
  196. {
  197. Const    *coffset;
  198. Param    *poffset;
  199. ParamListInfo paramLI;
  200. int i;
  201. switch (nodeTag(limoffset))
  202. {
  203. case T_Const:
  204. coffset = (Const *) limoffset;
  205. offset = (int) (coffset->constvalue);
  206. break;
  207. case T_Param:
  208. poffset = (Param *) limoffset;
  209. paramLI = estate->es_param_list_info;
  210. if (paramLI == NULL)
  211. elog(ERROR, "parameter for limit offset not in executor state");
  212. for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
  213. {
  214. if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == poffset->paramid)
  215. break;
  216. }
  217. if (paramLI[i].kind == PARAM_INVALID)
  218. elog(ERROR, "parameter for limit offset not in executor state");
  219. if (paramLI[i].isnull)
  220. elog(ERROR, "limit offset cannot be NULL value");
  221. offset = (int) (paramLI[i].value);
  222. break;
  223. default:
  224. elog(ERROR, "unexpected node type %d as limit offset", nodeTag(limoffset));
  225. }
  226. if (offset < 0)
  227. elog(ERROR, "limit offset cannot be negative");
  228. }
  229. /*
  230.  * if given get the count of the LIMIT clause
  231.  */
  232. if (limcount != NULL)
  233. {
  234. Const    *ccount;
  235. Param    *pcount;
  236. ParamListInfo paramLI;
  237. int i;
  238. switch (nodeTag(limcount))
  239. {
  240. case T_Const:
  241. ccount = (Const *) limcount;
  242. count = (int) (ccount->constvalue);
  243. break;
  244. case T_Param:
  245. pcount = (Param *) limcount;
  246. paramLI = estate->es_param_list_info;
  247. if (paramLI == NULL)
  248. elog(ERROR, "parameter for limit count not in executor state");
  249. for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
  250. {
  251. if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == pcount->paramid)
  252. break;
  253. }
  254. if (paramLI[i].kind == PARAM_INVALID)
  255. elog(ERROR, "parameter for limit count not in executor state");
  256. if (paramLI[i].isnull)
  257. elog(ERROR, "limit count cannot be NULL value");
  258. count = (int) (paramLI[i].value);
  259. break;
  260. default:
  261. elog(ERROR, "unexpected node type %d as limit count", nodeTag(limcount));
  262. }
  263. if (count < 0)
  264. elog(ERROR, "limit count cannot be negative");
  265. }
  266. switch (feature)
  267. {
  268. case EXEC_RUN:
  269. result = ExecutePlan(estate,
  270.  plan,
  271.  operation,
  272.  offset,
  273.  count,
  274.  ForwardScanDirection,
  275.  destfunc);
  276. break;
  277. case EXEC_FOR:
  278. result = ExecutePlan(estate,
  279.  plan,
  280.  operation,
  281.  offset,
  282.  count,
  283.  ForwardScanDirection,
  284.  destfunc);
  285. break;
  286. /*
  287.  * retrieve next n "backward" tuples
  288.  */
  289. case EXEC_BACK:
  290. result = ExecutePlan(estate,
  291.  plan,
  292.  operation,
  293.  offset,
  294.  count,
  295.  BackwardScanDirection,
  296.  destfunc);
  297. break;
  298. /*
  299.  * return one tuple but don't "retrieve" it. (this is used by
  300.  * the rule manager..) -cim 9/14/89
  301.  */
  302. case EXEC_RETONE:
  303. result = ExecutePlan(estate,
  304.  plan,
  305.  operation,
  306.  0,
  307.  ONE_TUPLE,
  308.  ForwardScanDirection,
  309.  destfunc);
  310. break;
  311. default:
  312. result = NULL;
  313. elog(DEBUG, "ExecutorRun: Unknown feature %d", feature);
  314. break;
  315. }
  316. (*destfunc->cleanup) (destfunc);
  317. return result;
  318. }
  319. /* ----------------------------------------------------------------
  320.  * ExecutorEnd
  321.  *
  322.  * This routine must be called at the end of any execution of any
  323.  * query plan
  324.  *
  325.  * returns (AttrInfo*) which describes the attributes of the tuples to
  326.  * be returned by the query.
  327.  *
  328.  * ----------------------------------------------------------------
  329.  */
  330. void
  331. ExecutorEnd(QueryDesc *queryDesc, EState *estate)
  332. {
  333. /* sanity checks */
  334. Assert(queryDesc != NULL);
  335. EndPlan(queryDesc->plantree, estate);
  336. /* XXX - clean up some more from ExecutorStart() - er1p */
  337. if (NULL == estate->es_snapshot)
  338. {
  339. /* nothing to free */
  340. }
  341. else
  342. {
  343. if (estate->es_snapshot->xcnt > 0)
  344. pfree(estate->es_snapshot->xip);
  345. pfree(estate->es_snapshot);
  346. }
  347. if (NULL == estate->es_param_exec_vals)
  348. {
  349. /* nothing to free */
  350. }
  351. else
  352. {
  353. pfree(estate->es_param_exec_vals);
  354. estate->es_param_exec_vals = NULL;
  355. }
  356. /* restore saved refcounts. */
  357. BufferRefCountRestore(estate->es_refcount);
  358. }
  359. void
  360. ExecCheckPerms(CmdType operation,
  361.    int resultRelation,
  362.    List *rangeTable,
  363.    Query *parseTree)
  364. {
  365. int i = 1;
  366. Oid relid;
  367. HeapTuple htup;
  368. List    *lp;
  369. List    *qvars,
  370.    *tvars;
  371. int32 ok = 1,
  372. aclcheck_result = -1;
  373. char    *opstr;
  374. NameData rname;
  375. char    *userName;
  376. #define CHECK(MODE) pg_aclcheck(rname.data, userName, MODE)
  377. userName = GetPgUserName();
  378. foreach(lp, rangeTable)
  379. {
  380. RangeTblEntry *rte = lfirst(lp);
  381. if (rte->skipAcl)
  382. {
  383. /*
  384.  * This happens if the access to this table is due to a view
  385.  * query rewriting - the rewrite handler checked the
  386.  * permissions against the view owner, so we just skip this
  387.  * entry.
  388.  */
  389. continue;
  390. }
  391. relid = rte->relid;
  392. htup = SearchSysCacheTuple(RELOID,
  393.    ObjectIdGetDatum(relid),
  394.    0, 0, 0);
  395. if (!HeapTupleIsValid(htup))
  396. elog(ERROR, "ExecCheckPerms: bogus RT relid: %u", relid);
  397. StrNCpy(rname.data,
  398. ((Form_pg_class) GETSTRUCT(htup))->relname.data,
  399. NAMEDATALEN);
  400. if (i == resultRelation)
  401. { /* this is the result relation */
  402. qvars = pull_varnos(parseTree->qual);
  403. tvars = pull_varnos((Node *) parseTree->targetList);
  404. if (intMember(resultRelation, qvars) ||
  405. intMember(resultRelation, tvars))
  406. {
  407. /* result relation is scanned */
  408. ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
  409. opstr = "read";
  410. if (!ok)
  411. break;
  412. }
  413. switch (operation)
  414. {
  415. case CMD_INSERT:
  416. ok = ((aclcheck_result = CHECK(ACL_AP)) == ACLCHECK_OK) ||
  417. ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
  418. opstr = "append";
  419. break;
  420. case CMD_DELETE:
  421. case CMD_UPDATE:
  422. ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
  423. opstr = "write";
  424. break;
  425. default:
  426. elog(ERROR, "ExecCheckPerms: bogus operation %d",
  427.  operation);
  428. }
  429. }
  430. else
  431. {
  432. ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
  433. opstr = "read";
  434. }
  435. if (!ok)
  436. break;
  437. ++i;
  438. }
  439. if (!ok)
  440. elog(ERROR, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
  441. if (parseTree != NULL && parseTree->rowMark != NULL)
  442. {
  443. foreach(lp, parseTree->rowMark)
  444. {
  445. RowMark    *rm = lfirst(lp);
  446. if (!(rm->info & ROW_ACL_FOR_UPDATE))
  447. continue;
  448. relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
  449. htup = SearchSysCacheTuple(RELOID,
  450.    ObjectIdGetDatum(relid),
  451.    0, 0, 0);
  452. if (!HeapTupleIsValid(htup))
  453. elog(ERROR, "ExecCheckPerms: bogus RT relid: %u", relid);
  454. StrNCpy(rname.data,
  455. ((Form_pg_class) GETSTRUCT(htup))->relname.data,
  456. NAMEDATALEN);
  457. ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
  458. opstr = "write";
  459. if (!ok)
  460. elog(ERROR, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
  461. }
  462. }
  463. }
  464. /* ===============================================================
  465.  * ===============================================================
  466.  static routines follow
  467.  * ===============================================================
  468.  * ===============================================================
  469.  */
  470. typedef struct execRowMark
  471. {
  472. Relation relation;
  473. Index rti;
  474. char resname[32];
  475. } execRowMark;
  476. typedef struct evalPlanQual
  477. {
  478. Plan    *plan;
  479. Index rti;
  480. EState estate;
  481. struct evalPlanQual *free;
  482. } evalPlanQual;
  483. /* ----------------------------------------------------------------
  484.  * InitPlan
  485.  *
  486.  * Initializes the query plan: open files, allocate storage
  487.  * and start up the rule manager
  488.  * ----------------------------------------------------------------
  489.  */
  490. static TupleDesc
  491. InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
  492. {
  493. List    *rangeTable;
  494. int resultRelation;
  495. Relation intoRelationDesc;
  496. TupleDesc tupType;
  497. List    *targetList;
  498. int len;
  499. /*
  500.  * get information from query descriptor
  501.  */
  502. rangeTable = parseTree->rtable;
  503. resultRelation = parseTree->resultRelation;
  504. #ifndef NO_SECURITY
  505. ExecCheckPerms(operation, resultRelation, rangeTable, parseTree);
  506. #endif
  507. /*
  508.  * initialize the node's execution state
  509.  */
  510. estate->es_range_table = rangeTable;
  511. /*
  512.  * initialize the BaseId counter so node base_id's are assigned
  513.  * correctly.  Someday baseid's will have to be stored someplace other
  514.  * than estate because they should be unique per query planned.
  515.  */
  516. estate->es_BaseId = 1;
  517. /*
  518.  * initialize result relation stuff
  519.  */
  520. if (resultRelation != 0 && operation != CMD_SELECT)
  521. {
  522. /*
  523.  * if we have a result relation, open it and initialize the result
  524.  * relation info stuff.
  525.  */
  526. RelationInfo *resultRelationInfo;
  527. Index resultRelationIndex;
  528. RangeTblEntry *rtentry;
  529. Oid resultRelationOid;
  530. Relation resultRelationDesc;
  531. resultRelationIndex = resultRelation;
  532. rtentry = rt_fetch(resultRelationIndex, rangeTable);
  533. resultRelationOid = rtentry->relid;
  534. resultRelationDesc = heap_open(resultRelationOid);
  535. if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
  536. elog(ERROR, "You can't change sequence relation %s",
  537.  resultRelationDesc->rd_rel->relname.data);
  538. LockRelation(resultRelationDesc, RowExclusiveLock);
  539. resultRelationInfo = makeNode(RelationInfo);
  540. resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
  541. resultRelationInfo->ri_RelationDesc = resultRelationDesc;
  542. resultRelationInfo->ri_NumIndices = 0;
  543. resultRelationInfo->ri_IndexRelationDescs = NULL;
  544. resultRelationInfo->ri_IndexRelationInfo = NULL;
  545. /*
  546.  * open indices on result relation and save descriptors in the
  547.  * result relation information..
  548.  */
  549. if (operation != CMD_DELETE)
  550. ExecOpenIndices(resultRelationOid, resultRelationInfo);
  551. estate->es_result_relation_info = resultRelationInfo;
  552. }
  553. else
  554. {
  555. /*
  556.  * if no result relation, then set state appropriately
  557.  */
  558. estate->es_result_relation_info = NULL;
  559. }
  560. /*
  561.  * Have to lock relations selected for update
  562.  */
  563. estate->es_rowMark = NULL;
  564. if (parseTree->rowMark != NULL)
  565. {
  566. Relation relation;
  567. Oid relid;
  568. RowMark    *rm;
  569. List    *l;
  570. execRowMark *erm;
  571. foreach(l, parseTree->rowMark)
  572. {
  573. rm = lfirst(l);
  574. relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
  575. relation = heap_open(relid);
  576. LockRelation(relation, RowShareLock);
  577. if (!(rm->info & ROW_MARK_FOR_UPDATE))
  578. continue;
  579. erm = (execRowMark *) palloc(sizeof(execRowMark));
  580. erm->relation = relation;
  581. erm->rti = rm->rti;
  582. sprintf(erm->resname, "ctid%u", rm->rti);
  583. estate->es_rowMark = lappend(estate->es_rowMark, erm);
  584. }
  585. }
  586. /*
  587.  * initialize the executor "tuple" table.
  588.  */
  589. {
  590. int nSlots = ExecCountSlotsNode(plan);
  591. TupleTable tupleTable = ExecCreateTupleTable(nSlots + 10); /* why add ten? - jolly */
  592. estate->es_tupleTable = tupleTable;
  593. }
  594. /*
  595.  * initialize the private state information for all the nodes in the
  596.  * query tree. This opens files, allocates storage and leaves us
  597.  * ready to start processing tuples..
  598.  */
  599. ExecInitNode(plan, estate, NULL);
  600. /*
  601.  * get the tuple descriptor describing the type of tuples to return..
  602.  * (this is especially important if we are creating a relation with
  603.  * "retrieve into")
  604.  */
  605. tupType = ExecGetTupType(plan); /* tuple descriptor */
  606. targetList = plan->targetlist;
  607. len = ExecTargetListLength(targetList); /* number of attributes */
  608. /*
  609.  * now that we have the target list, initialize the junk filter if
  610.  * this is a REPLACE or a DELETE query. We also init the junk filter
  611.  * if this is an append query (there might be some rule lock info
  612.  * there...) NOTE: in the future we might want to initialize the junk
  613.  * filter for all queries. SELECT added by daveh@insightdist.com
  614.  * 5/20/98 to allow ORDER/GROUP BY have an identifier missing from the
  615.  * target.
  616.  */
  617. {
  618. bool junk_filter_needed = false;
  619. List    *tlist;
  620. if (operation == CMD_SELECT)
  621. {
  622. foreach(tlist, targetList)
  623. {
  624. TargetEntry *tle = lfirst(tlist);
  625. if (tle->resdom->resjunk)
  626. {
  627. junk_filter_needed = true;
  628. break;
  629. }
  630. }
  631. }
  632. if (operation == CMD_UPDATE || operation == CMD_DELETE ||
  633. operation == CMD_INSERT ||
  634. (operation == CMD_SELECT && junk_filter_needed))
  635. {
  636. JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
  637. estate->es_junkFilter = j;
  638. if (operation == CMD_SELECT)
  639. tupType = j->jf_cleanTupType;
  640. }
  641. else
  642. estate->es_junkFilter = NULL;
  643. }
  644. /*
  645.  * initialize the "into" relation
  646.  */
  647. intoRelationDesc = (Relation) NULL;
  648. if (operation == CMD_SELECT)
  649. {
  650. char    *intoName;
  651. Oid intoRelationId;
  652. TupleDesc tupdesc;
  653. if (!parseTree->isPortal)
  654. {
  655. /*
  656.  * a select into table
  657.  */
  658. if (parseTree->into != NULL)
  659. {
  660. /*
  661.  * create the "into" relation
  662.  */
  663. intoName = parseTree->into;
  664. /*
  665.  * have to copy tupType to get rid of constraints
  666.  */
  667. tupdesc = CreateTupleDescCopy(tupType);
  668. intoRelationId = heap_create_with_catalog(intoName,
  669.    tupdesc, RELKIND_RELATION, parseTree->isTemp);
  670. FreeTupleDesc(tupdesc);
  671. /*
  672.  * XXX rather than having to call setheapoverride(true)
  673.  * and then back to false, we should change the arguments
  674.  * to heap_open() instead..
  675.  */
  676. setheapoverride(true);
  677. intoRelationDesc = heap_open(intoRelationId);
  678. setheapoverride(false);
  679. }
  680. }
  681. }
  682. estate->es_into_relation_descriptor = intoRelationDesc;
  683. estate->es_origPlan = plan;
  684. estate->es_evalPlanQual = NULL;
  685. estate->es_evTuple = NULL;
  686. estate->es_useEvalPlan = false;
  687. return tupType;
  688. }
  689. /* ----------------------------------------------------------------
  690.  * EndPlan
  691.  *
  692.  * Cleans up the query plan -- closes files and free up storages
  693.  * ----------------------------------------------------------------
  694.  */
  695. static void
  696. EndPlan(Plan *plan, EState *estate)
  697. {
  698. RelationInfo *resultRelationInfo;
  699. Relation intoRelationDesc;
  700. /*
  701.  * get information from state
  702.  */
  703. resultRelationInfo = estate->es_result_relation_info;
  704. intoRelationDesc = estate->es_into_relation_descriptor;
  705. /*
  706.  * shut down the query
  707.  */
  708. ExecEndNode(plan, plan);
  709. /*
  710.  * destroy the executor "tuple" table.
  711.  */
  712. {
  713. TupleTable tupleTable = (TupleTable) estate->es_tupleTable;
  714. ExecDestroyTupleTable(tupleTable, true); /* was missing last arg */
  715. estate->es_tupleTable = NULL;
  716. }
  717. /*
  718.  * close the result relations if necessary
  719.  */
  720. if (resultRelationInfo != NULL)
  721. {
  722. Relation resultRelationDesc;
  723. resultRelationDesc = resultRelationInfo->ri_RelationDesc;
  724. heap_close(resultRelationDesc);
  725. /*
  726.  * close indices on the result relation
  727.  */
  728. ExecCloseIndices(resultRelationInfo);
  729. }
  730. /*
  731.  * close the "into" relation if necessary
  732.  */
  733. if (intoRelationDesc != NULL)
  734. heap_close(intoRelationDesc);
  735. }
  736. /* ----------------------------------------------------------------
  737.  * ExecutePlan
  738.  *
  739.  * processes the query plan to retrieve 'tupleCount' tuples in the
  740.  * direction specified.
  741.  * Retrieves all tuples if tupleCount is 0
  742.  *
  743.  * result is either a slot containing a tuple in the case
  744.  * of a RETRIEVE or NULL otherwise.
  745.  *
  746.  * ----------------------------------------------------------------
  747.  */
  748. /* the ctid attribute is a 'junk' attribute that is removed before the
  749.    user can see it*/
  750. static TupleTableSlot *
  751. ExecutePlan(EState *estate,
  752. Plan *plan,
  753. CmdType operation,
  754. int offsetTuples,
  755. int numberTuples,
  756. ScanDirection direction,
  757. DestReceiver *destfunc)
  758. {
  759. JunkFilter *junkfilter;
  760. TupleTableSlot *slot;
  761. ItemPointer tupleid = NULL;
  762. ItemPointerData tuple_ctid;
  763. int current_tuple_count;
  764. TupleTableSlot *result;
  765. /*
  766.  * initialize local variables
  767.  */
  768. slot = NULL;
  769. current_tuple_count = 0;
  770. result = NULL;
  771. /*
  772.  * Set the direction.
  773.  */
  774. estate->es_direction = direction;
  775. /*
  776.  * Loop until we've processed the proper number of tuples from the
  777.  * plan..
  778.  */
  779. for (;;)
  780. {
  781. /*
  782.  * Execute the plan and obtain a tuple
  783.  */
  784. /* at the top level, the parent of a plan (2nd arg) is itself */
  785. lnext: ;
  786. if (estate->es_useEvalPlan)
  787. {
  788. slot = EvalPlanQualNext(estate);
  789. if (TupIsNull(slot))
  790. slot = ExecProcNode(plan, plan);
  791. }
  792. else
  793. slot = ExecProcNode(plan, plan);
  794. /*
  795.  * if the tuple is null, then we assume there is nothing more to
  796.  * process so we just return null...
  797.  */
  798. if (TupIsNull(slot))
  799. {
  800. result = NULL;
  801. break;
  802. }
  803. /*
  804.  * For now we completely execute the plan and skip result tuples
  805.  * if requested by LIMIT offset. Finally we should try to do it in
  806.  * deeper levels if possible (during index scan) - Jan
  807.  */
  808. if (offsetTuples > 0)
  809. {
  810. --offsetTuples;
  811. continue;
  812. }
  813. /*
  814.  * if we have a junk filter, then project a new tuple with the
  815.  * junk removed.
  816.  *
  817.  * Store this new "clean" tuple in the place of the original tuple.
  818.  *
  819.  * Also, extract all the junk information we need.
  820.  */
  821. if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
  822. {
  823. Datum datum;
  824. HeapTuple newTuple;
  825. bool isNull;
  826. /*
  827.  * extract the 'ctid' junk attribute.
  828.  */
  829. if (operation == CMD_UPDATE || operation == CMD_DELETE)
  830. {
  831. if (!ExecGetJunkAttribute(junkfilter,
  832.   slot,
  833.   "ctid",
  834.   &datum,
  835.   &isNull))
  836. elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!");
  837. if (isNull)
  838. elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!");
  839. tupleid = (ItemPointer) DatumGetPointer(datum);
  840. tuple_ctid = *tupleid; /* make sure we don't free the
  841.  * ctid!! */
  842. tupleid = &tuple_ctid;
  843. }
  844. else if (estate->es_rowMark != NULL)
  845. {
  846. List    *l;
  847. execRowMark *erm;
  848. Buffer buffer;
  849. HeapTupleData tuple;
  850. TupleTableSlot *newSlot;
  851. int test;
  852. lmark: ;
  853. foreach(l, estate->es_rowMark)
  854. {
  855. erm = lfirst(l);
  856. if (!ExecGetJunkAttribute(junkfilter,
  857.   slot,
  858.   erm->resname,
  859.   &datum,
  860.   &isNull))
  861. elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!", erm->resname);
  862. if (isNull)
  863. elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!", erm->resname);
  864. tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
  865. test = heap_mark4update(erm->relation, &tuple, &buffer);
  866. ReleaseBuffer(buffer);
  867. switch (test)
  868. {
  869. case HeapTupleSelfUpdated:
  870. case HeapTupleMayBeUpdated:
  871. break;
  872. case HeapTupleUpdated:
  873. if (XactIsoLevel == XACT_SERIALIZABLE)
  874. {
  875. elog(ERROR, "Can't serialize access due to concurrent update");
  876. return (NULL);
  877. }
  878. else if (!(ItemPointerEquals(&(tuple.t_self),
  879.   (ItemPointer) DatumGetPointer(datum))))
  880. {
  881. newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));
  882. if (!(TupIsNull(newSlot)))
  883. {
  884. slot = newSlot;
  885. estate->es_useEvalPlan = true;
  886. goto lmark;
  887. }
  888. }
  889. /*
  890.  * if tuple was deleted or PlanQual failed for
  891.  * updated tuple - we have not return this
  892.  * tuple!
  893.  */
  894. goto lnext;
  895. default:
  896. elog(ERROR, "Unknown status %u from heap_mark4update", test);
  897. return (NULL);
  898. }
  899. }
  900. }
  901. /*
  902.  * Finally create a new "clean" tuple with all junk attributes
  903.  * removed
  904.  */
  905. newTuple = ExecRemoveJunk(junkfilter, slot);
  906. slot = ExecStoreTuple(newTuple, /* tuple to store */
  907.   slot, /* destination slot */
  908.   InvalidBuffer, /* this tuple has no
  909.  * buffer */
  910.   true); /* tuple should be pfreed */
  911. } /* if (junkfilter... */
  912. /*
  913.  * now that we have a tuple, do the appropriate thing with it..
  914.  * either return it to the user, add it to a relation someplace,
  915.  * delete it from a relation, or modify some of it's attributes.
  916.  */
  917. switch (operation)
  918. {
  919. case CMD_SELECT:
  920. ExecRetrieve(slot, /* slot containing tuple */
  921.  destfunc, /* destination's tuple-receiver
  922.  * obj */
  923.  estate); /* */
  924. result = slot;
  925. break;
  926. case CMD_INSERT:
  927. ExecAppend(slot, tupleid, estate);
  928. result = NULL;
  929. break;
  930. case CMD_DELETE:
  931. ExecDelete(slot, tupleid, estate);
  932. result = NULL;
  933. break;
  934. case CMD_UPDATE:
  935. ExecReplace(slot, tupleid, estate);
  936. result = NULL;
  937. break;
  938. default:
  939. elog(DEBUG, "ExecutePlan: unknown operation in queryDesc");
  940. result = NULL;
  941. break;
  942. }
  943. /*
  944.  * check our tuple count.. if we've returned the proper number
  945.  * then return, else loop again and process more tuples..
  946.  */
  947. current_tuple_count += 1;
  948. if (numberTuples == current_tuple_count)
  949. break;
  950. }
  951. /*
  952.  * here, result is either a slot containing a tuple in the case of a
  953.  * RETRIEVE or NULL otherwise.
  954.  */
  955. return result;
  956. }
  957. /* ----------------------------------------------------------------
  958.  * ExecRetrieve
  959.  *
  960.  * RETRIEVEs are easy.. we just pass the tuple to the appropriate
  961.  * print function.  The only complexity is when we do a
  962.  * "retrieve into", in which case we insert the tuple into
  963.  * the appropriate relation (note: this is a newly created relation
  964.  * so we don't need to worry about indices or locks.)
  965.  * ----------------------------------------------------------------
  966.  */
  967. static void
  968. ExecRetrieve(TupleTableSlot *slot,
  969.  DestReceiver *destfunc,
  970.  EState *estate)
  971. {
  972. HeapTuple tuple;
  973. TupleDesc attrtype;
  974. /*
  975.  * get the heap tuple out of the tuple table slot
  976.  */
  977. tuple = slot->val;
  978. attrtype = slot->ttc_tupleDescriptor;
  979. /*
  980.  * insert the tuple into the "into relation"
  981.  */
  982. if (estate->es_into_relation_descriptor != NULL)
  983. {
  984. heap_insert(estate->es_into_relation_descriptor, tuple);
  985. IncrAppended();
  986. }
  987. /*
  988.  * send the tuple to the front end (or the screen)
  989.  */
  990. (*destfunc->receiveTuple) (tuple, attrtype, destfunc);
  991. IncrRetrieved();
  992. (estate->es_processed)++;
  993. }
  994. /* ----------------------------------------------------------------
  995.  * ExecAppend
  996.  *
  997.  * APPENDs are trickier.. we have to insert the tuple into
  998.  * the base relation and insert appropriate tuples into the
  999.  * index relations.
  1000.  * ----------------------------------------------------------------
  1001.  */
  1002. static void
  1003. ExecAppend(TupleTableSlot *slot,
  1004.    ItemPointer tupleid,
  1005.    EState *estate)
  1006. {
  1007. HeapTuple tuple;
  1008. RelationInfo *resultRelationInfo;
  1009. Relation resultRelationDesc;
  1010. int numIndices;
  1011. Oid newId;
  1012. /*
  1013.  * get the heap tuple out of the tuple table slot
  1014.  */
  1015. tuple = slot->val;
  1016. /*
  1017.  * get information on the result relation
  1018.  */
  1019. resultRelationInfo = estate->es_result_relation_info;
  1020. resultRelationDesc = resultRelationInfo->ri_RelationDesc;
  1021. /*
  1022.  * have to add code to preform unique checking here. cim -12/1/89
  1023.  */
  1024. /* BEFORE ROW INSERT Triggers */
  1025. if (resultRelationDesc->trigdesc &&
  1026. resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
  1027. {
  1028. HeapTuple newtuple;
  1029. newtuple = ExecBRInsertTriggers(resultRelationDesc, tuple);
  1030. if (newtuple == NULL) /* "do nothing" */
  1031. return;
  1032. if (newtuple != tuple) /* modified by Trigger(s) */
  1033. {
  1034. Assert(slot->ttc_shouldFree);
  1035. pfree(tuple);
  1036. slot->val = tuple = newtuple;
  1037. }
  1038. }
  1039. /*
  1040.  * Check the constraints of a tuple
  1041.  */
  1042. if (resultRelationDesc->rd_att->constr)
  1043. ExecConstraints("ExecAppend", resultRelationDesc, tuple, estate);
  1044. /*
  1045.  * insert the tuple
  1046.  */
  1047. newId = heap_insert(resultRelationDesc, /* relation desc */
  1048. tuple); /* heap tuple */
  1049. IncrAppended();
  1050. /*
  1051.  * process indices
  1052.  *
  1053.  * Note: heap_insert adds a new tuple to a relation.  As a side effect,
  1054.  * the tupleid of the new tuple is placed in the new tuple's t_ctid
  1055.  * field.
  1056.  */
  1057. numIndices = resultRelationInfo->ri_NumIndices;
  1058. if (numIndices > 0)
  1059. ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
  1060. (estate->es_processed)++;
  1061. estate->es_lastoid = newId;
  1062. /* AFTER ROW INSERT Triggers */
  1063. if (resultRelationDesc->trigdesc &&
  1064.  resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
  1065. ExecARInsertTriggers(resultRelationDesc, tuple);
  1066. }
  1067. /* ----------------------------------------------------------------
  1068.  * ExecDelete
  1069.  *
  1070.  * DELETE is like append, we delete the tuple and its
  1071.  * index tuples.
  1072.  * ----------------------------------------------------------------
  1073.  */
  1074. static void
  1075. ExecDelete(TupleTableSlot *slot,
  1076.    ItemPointer tupleid,
  1077.    EState *estate)
  1078. {
  1079. RelationInfo *resultRelationInfo;
  1080. Relation resultRelationDesc;
  1081. ItemPointerData ctid;
  1082. int result;
  1083. /*
  1084.  * get the result relation information
  1085.  */
  1086. resultRelationInfo = estate->es_result_relation_info;
  1087. resultRelationDesc = resultRelationInfo->ri_RelationDesc;
  1088. /* BEFORE ROW DELETE Triggers */
  1089. if (resultRelationDesc->trigdesc &&
  1090. resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
  1091. {
  1092. bool dodelete;
  1093. dodelete = ExecBRDeleteTriggers(estate, tupleid);
  1094. if (!dodelete) /* "do nothing" */
  1095. return;
  1096. }
  1097. /*
  1098.  * delete the tuple
  1099.  */
  1100. ldelete:;
  1101. result = heap_delete(resultRelationDesc, tupleid, &ctid);
  1102. switch (result)
  1103. {
  1104. case HeapTupleSelfUpdated:
  1105. return;
  1106. case HeapTupleMayBeUpdated:
  1107. break;
  1108. case HeapTupleUpdated:
  1109. if (XactIsoLevel == XACT_SERIALIZABLE)
  1110. elog(ERROR, "Can't serialize access due to concurrent update");
  1111. else if (!(ItemPointerEquals(tupleid, &ctid)))
  1112. {
  1113. TupleTableSlot *epqslot = EvalPlanQual(estate,
  1114.   resultRelationInfo->ri_RangeTableIndex, &ctid);
  1115. if (!TupIsNull(epqslot))
  1116. {
  1117. *tupleid = ctid;
  1118. goto ldelete;
  1119. }
  1120. }
  1121. return;
  1122. default:
  1123. elog(ERROR, "Unknown status %u from heap_delete", result);
  1124. return;
  1125. }
  1126. IncrDeleted();
  1127. (estate->es_processed)++;
  1128. /*
  1129.  * Note: Normally one would think that we have to delete index tuples
  1130.  * associated with the heap tuple now..
  1131.  *
  1132.  * ... but in POSTGRES, we have no need to do this because the vacuum
  1133.  * daemon automatically opens an index scan and deletes index tuples
  1134.  * when it finds deleted heap tuples. -cim 9/27/89
  1135.  */
  1136. /* AFTER ROW DELETE Triggers */
  1137. if (resultRelationDesc->trigdesc &&
  1138.  resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
  1139. ExecARDeleteTriggers(estate, tupleid);
  1140. }
  1141. /* ----------------------------------------------------------------
  1142.  * ExecReplace
  1143.  *
  1144.  * note: we can't run replace queries with transactions
  1145.  * off because replaces are actually appends and our
  1146.  * scan will mistakenly loop forever, replacing the tuple
  1147.  * it just appended.. This should be fixed but until it
  1148.  * is, we don't want to get stuck in an infinite loop
  1149.  * which corrupts your database..
  1150.  * ----------------------------------------------------------------
  1151.  */
  1152. static void
  1153. ExecReplace(TupleTableSlot *slot,
  1154. ItemPointer tupleid,
  1155. EState *estate)
  1156. {
  1157. HeapTuple tuple;
  1158. RelationInfo *resultRelationInfo;
  1159. Relation resultRelationDesc;
  1160. ItemPointerData ctid;
  1161. int result;
  1162. int numIndices;
  1163. /*
  1164.  * abort the operation if not running transactions
  1165.  */
  1166. if (IsBootstrapProcessingMode())
  1167. {
  1168. elog(DEBUG, "ExecReplace: replace can't run without transactions");
  1169. return;
  1170. }
  1171. /*
  1172.  * get the heap tuple out of the tuple table slot
  1173.  */
  1174. tuple = slot->val;
  1175. /*
  1176.  * get the result relation information
  1177.  */
  1178. resultRelationInfo = estate->es_result_relation_info;
  1179. resultRelationDesc = resultRelationInfo->ri_RelationDesc;
  1180. /*
  1181.  * have to add code to preform unique checking here. in the event of
  1182.  * unique tuples, this becomes a deletion of the original tuple
  1183.  * affected by the replace. cim -12/1/89
  1184.  */
  1185. /* BEFORE ROW UPDATE Triggers */
  1186. if (resultRelationDesc->trigdesc &&
  1187. resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
  1188. {
  1189. HeapTuple newtuple;
  1190. newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);
  1191. if (newtuple == NULL) /* "do nothing" */
  1192. return;
  1193. if (newtuple != tuple) /* modified by Trigger(s) */
  1194. {
  1195. Assert(slot->ttc_shouldFree);
  1196. pfree(tuple);
  1197. slot->val = tuple = newtuple;
  1198. }
  1199. }
  1200. /*
  1201.  * Check the constraints of a tuple
  1202.  */
  1203. if (resultRelationDesc->rd_att->constr)
  1204. ExecConstraints("ExecReplace", resultRelationDesc, tuple, estate);
  1205. /*
  1206.  * replace the heap tuple
  1207.  */
  1208. lreplace:;
  1209. result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid);
  1210. switch (result)
  1211. {
  1212. case HeapTupleSelfUpdated:
  1213. return;
  1214. case HeapTupleMayBeUpdated:
  1215. break;
  1216. case HeapTupleUpdated:
  1217. if (XactIsoLevel == XACT_SERIALIZABLE)
  1218. elog(ERROR, "Can't serialize access due to concurrent update");
  1219. else if (!(ItemPointerEquals(tupleid, &ctid)))
  1220. {
  1221. TupleTableSlot *epqslot = EvalPlanQual(estate,
  1222.   resultRelationInfo->ri_RangeTableIndex, &ctid);
  1223. if (!TupIsNull(epqslot))
  1224. {
  1225. *tupleid = ctid;
  1226. tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
  1227. slot = ExecStoreTuple(tuple, slot, InvalidBuffer, true);
  1228. goto lreplace;
  1229. }
  1230. }
  1231. return;
  1232. default:
  1233. elog(ERROR, "Unknown status %u from heap_replace", result);
  1234. return;
  1235. }
  1236. IncrReplaced();
  1237. (estate->es_processed)++;
  1238. /*
  1239.  * Note: instead of having to update the old index tuples associated
  1240.  * with the heap tuple, all we do is form and insert new index
  1241.  * tuples..  This is because replaces are actually deletes and inserts
  1242.  * and index tuple deletion is done automagically by the vaccuum
  1243.  * deamon.. All we do is insert new index tuples.  -cim 9/27/89
  1244.  */
  1245. /*
  1246.  * process indices
  1247.  *
  1248.  * heap_replace updates a tuple in the base relation by invalidating it
  1249.  * and then appending a new tuple to the relation. As a side effect,
  1250.  * the tupleid of the new tuple is placed in the new tuple's t_ctid
  1251.  * field.  So we now insert index tuples using the new tupleid stored
  1252.  * there.
  1253.  */
  1254. numIndices = resultRelationInfo->ri_NumIndices;
  1255. if (numIndices > 0)
  1256. ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
  1257. /* AFTER ROW UPDATE Triggers */
  1258. if (resultRelationDesc->trigdesc &&
  1259.  resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
  1260. ExecARUpdateTriggers(estate, tupleid, tuple);
  1261. }
  1262. #ifdef NOT_USED
  1263. static HeapTuple
  1264. ExecAttrDefault(Relation rel, HeapTuple tuple)
  1265. {
  1266. int ndef = rel->rd_att->constr->num_defval;
  1267. AttrDefault *attrdef = rel->rd_att->constr->defval;
  1268. ExprContext *econtext = makeNode(ExprContext);
  1269. HeapTuple newtuple;
  1270. Node    *expr;
  1271. bool isnull;
  1272. bool isdone;
  1273. Datum val;
  1274. Datum    *replValue = NULL;
  1275. char    *replNull = NULL;
  1276. char    *repl = NULL;
  1277. int i;
  1278. econtext->ecxt_scantuple = NULL; /* scan tuple slot */
  1279. econtext->ecxt_innertuple = NULL; /* inner tuple slot */
  1280. econtext->ecxt_outertuple = NULL; /* outer tuple slot */
  1281. econtext->ecxt_relation = NULL; /* relation */
  1282. econtext->ecxt_relid = 0; /* relid */
  1283. econtext->ecxt_param_list_info = NULL; /* param list info */
  1284. econtext->ecxt_param_exec_vals = NULL; /* exec param values */
  1285. econtext->ecxt_range_table = NULL; /* range table */
  1286. for (i = 0; i < ndef; i++)
  1287. {
  1288. if (!heap_attisnull(tuple, attrdef[i].adnum))
  1289. continue;
  1290. expr = (Node *) stringToNode(attrdef[i].adbin);
  1291. val = ExecEvalExpr(expr, econtext, &isnull, &isdone);
  1292. pfree(expr);
  1293. if (isnull)
  1294. continue;
  1295. if (repl == NULL)
  1296. {
  1297. repl = (char *) palloc(rel->rd_att->natts * sizeof(char));
  1298. replNull = (char *) palloc(rel->rd_att->natts * sizeof(char));
  1299. replValue = (Datum *) palloc(rel->rd_att->natts * sizeof(Datum));
  1300. MemSet(repl, ' ', rel->rd_att->natts * sizeof(char));
  1301. }
  1302. repl[attrdef[i].adnum - 1] = 'r';
  1303. replNull[attrdef[i].adnum - 1] = ' ';
  1304. replValue[attrdef[i].adnum - 1] = val;
  1305. }
  1306. pfree(econtext);
  1307. if (repl == NULL)
  1308. return tuple;
  1309. newtuple = heap_modifytuple(tuple, rel, replValue, replNull, repl);
  1310. pfree(repl);
  1311. pfree(tuple);
  1312. pfree(replNull);
  1313. pfree(replValue);
  1314. return newtuple;
  1315. }
  1316. #endif
  1317. static char *
  1318. ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
  1319. {
  1320. int ncheck = rel->rd_att->constr->num_check;
  1321. ConstrCheck *check = rel->rd_att->constr->check;
  1322. ExprContext *econtext = makeNode(ExprContext);
  1323. TupleTableSlot *slot = makeNode(TupleTableSlot);
  1324. RangeTblEntry *rte = makeNode(RangeTblEntry);
  1325. List    *rtlist;
  1326. List    *qual;
  1327. bool res;
  1328. int i;
  1329. slot->val = tuple;
  1330. slot->ttc_shouldFree = false;
  1331. slot->ttc_descIsNew = true;
  1332. slot->ttc_tupleDescriptor = rel->rd_att;
  1333. slot->ttc_buffer = InvalidBuffer;
  1334. slot->ttc_whichplan = -1;
  1335. rte->relname = nameout(&(rel->rd_rel->relname));
  1336. rte->refname = rte->relname;
  1337. rte->relid = RelationGetRelid(rel);
  1338. rte->inh = false;
  1339. rte->inFromCl = true;
  1340. rtlist = lcons(rte, NIL);
  1341. econtext->ecxt_scantuple = slot; /* scan tuple slot */
  1342. econtext->ecxt_innertuple = NULL; /* inner tuple slot */
  1343. econtext->ecxt_outertuple = NULL; /* outer tuple slot */
  1344. econtext->ecxt_relation = rel; /* relation */
  1345. econtext->ecxt_relid = 0; /* relid */
  1346. econtext->ecxt_param_list_info = NULL; /* param list info */
  1347. econtext->ecxt_param_exec_vals = NULL; /* exec param values */
  1348. econtext->ecxt_range_table = rtlist; /* range table */
  1349. if (estate->es_result_relation_constraints == NULL)
  1350. {
  1351. estate->es_result_relation_constraints =
  1352. (List **) palloc(ncheck * sizeof(List *));
  1353. for (i = 0; i < ncheck; i++)
  1354. {
  1355. qual = (List *) stringToNode(check[i].ccbin);
  1356. estate->es_result_relation_constraints[i] = qual;
  1357. }
  1358. }
  1359. for (i = 0; i < ncheck; i++)
  1360. {
  1361. qual = estate->es_result_relation_constraints[i];
  1362. res = ExecQual(qual, econtext);
  1363. if (!res)
  1364. return check[i].ccname;
  1365. }
  1366. pfree(slot);
  1367. pfree(rte->relname);
  1368. pfree(rte);
  1369. pfree(rtlist);
  1370. pfree(econtext);
  1371. return (char *) NULL;
  1372. }
  1373. void
  1374. ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
  1375. {
  1376. Assert(rel->rd_att->constr);
  1377. if (rel->rd_att->constr->has_not_null)
  1378. {
  1379. int attrChk;
  1380. for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)
  1381. {
  1382. if (rel->rd_att->attrs[attrChk - 1]->attnotnull && heap_attisnull(tuple, attrChk))
  1383. elog(ERROR, "%s: Fail to add null value in not null attribute %s",
  1384.   caller, rel->rd_att->attrs[attrChk - 1]->attname.data);
  1385. }
  1386. }
  1387. if (rel->rd_att->constr->num_check > 0)
  1388. {
  1389. char    *failed;
  1390. if ((failed = ExecRelCheck(rel, tuple, estate)) != NULL)
  1391. elog(ERROR, "%s: rejected due to CHECK constraint %s", caller, failed);
  1392. }
  1393. return;
  1394. }
  1395. TupleTableSlot *
  1396. EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
  1397. {
  1398. evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
  1399. evalPlanQual *oldepq;
  1400. EState    *epqstate = NULL;
  1401. Relation relation;
  1402. Buffer buffer;
  1403. HeapTupleData tuple;
  1404. bool endNode = true;
  1405. Assert(rti != 0);
  1406. if (epq != NULL && epq->rti == 0)
  1407. {
  1408. Assert(!(estate->es_useEvalPlan) &&
  1409.    epq->estate.es_evalPlanQual == NULL);
  1410. epq->rti = rti;
  1411. endNode = false;
  1412. }
  1413. /*
  1414.  * If this is request for another RTE - Ra, - then we have to check
  1415.  * wasn't PlanQual requested for Ra already and if so then Ra' row was
  1416.  * updated again and we have to re-start old execution for Ra and
  1417.  * forget all what we done after Ra was suspended. Cool? -:))
  1418.  */
  1419. if (epq != NULL && epq->rti != rti &&
  1420. epq->estate.es_evTuple[rti - 1] != NULL)
  1421. {
  1422. do
  1423. {
  1424. /* pop previous PlanQual from the stack */
  1425. epqstate = &(epq->estate);
  1426. oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
  1427. Assert(oldepq->rti != 0);
  1428. /* stop execution */
  1429. ExecEndNode(epq->plan, epq->plan);
  1430.     epqstate->es_tupleTable->next = 0;
  1431. pfree(epqstate->es_evTuple[epq->rti - 1]);
  1432. epqstate->es_evTuple[epq->rti - 1] = NULL;
  1433. /* push current PQ to freePQ stack */
  1434. oldepq->free = epq;
  1435. epq = oldepq;
  1436. } while (epq->rti != rti);
  1437. estate->es_evalPlanQual = (Pointer) epq;
  1438. }
  1439. /*
  1440.  * If we are requested for another RTE then we have to suspend
  1441.  * execution of current PlanQual and start execution for new one.
  1442.  */
  1443. if (epq == NULL || epq->rti != rti)
  1444. {
  1445. /* try to reuse plan used previously */
  1446. evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;
  1447. if (newepq == NULL) /* first call or freePQ stack is empty */
  1448. {
  1449. newepq = (evalPlanQual *) palloc(sizeof(evalPlanQual));
  1450. /* Init EState */
  1451. epqstate = &(newepq->estate);
  1452. memset(epqstate, 0, sizeof(EState));
  1453. epqstate->type = T_EState;
  1454. epqstate->es_direction = ForwardScanDirection;
  1455. epqstate->es_snapshot = estate->es_snapshot;
  1456. epqstate->es_range_table = estate->es_range_table;
  1457. epqstate->es_param_list_info = estate->es_param_list_info;
  1458. if (estate->es_origPlan->nParamExec > 0)
  1459. epqstate->es_param_exec_vals = (ParamExecData *)
  1460. palloc(estate->es_origPlan->nParamExec *
  1461.    sizeof(ParamExecData));
  1462. epqstate->es_tupleTable =
  1463. ExecCreateTupleTable(estate->es_tupleTable->size);
  1464. epqstate->es_refcount = estate->es_refcount;
  1465. /* ... rest */
  1466. newepq->plan = copyObject(estate->es_origPlan);
  1467. newepq->free = NULL;
  1468. epqstate->es_evTupleNull = (bool *)
  1469. palloc(length(estate->es_range_table) * sizeof(bool));
  1470. if (epq == NULL) /* first call */
  1471. {
  1472. epqstate->es_evTuple = (HeapTuple *)
  1473. palloc(length(estate->es_range_table) * sizeof(HeapTuple));
  1474. memset(epqstate->es_evTuple, 0,
  1475.  length(estate->es_range_table) * sizeof(HeapTuple));
  1476. }
  1477. else
  1478. epqstate->es_evTuple = epq->estate.es_evTuple;
  1479. }
  1480. else
  1481. epqstate = &(newepq->estate);
  1482. /* push current PQ to the stack */
  1483. epqstate->es_evalPlanQual = (Pointer) epq;
  1484. epq = newepq;
  1485. estate->es_evalPlanQual = (Pointer) epq;
  1486. epq->rti = rti;
  1487. endNode = false;
  1488. }
  1489. epqstate = &(epq->estate);
  1490. /*
  1491.  * Ok - we're requested for the same RTE (-:)). I'm not sure about
  1492.  * ability to use ExecReScan instead of ExecInitNode, so...
  1493.  */
  1494. if (endNode)
  1495. {
  1496. ExecEndNode(epq->plan, epq->plan);
  1497.     epqstate->es_tupleTable->next = 0;
  1498. }
  1499. /* free old RTE' tuple */
  1500. if (epqstate->es_evTuple[epq->rti - 1] != NULL)
  1501. {
  1502. pfree(epqstate->es_evTuple[epq->rti - 1]);
  1503. epqstate->es_evTuple[epq->rti - 1] = NULL;
  1504. }
  1505. /* ** fetch tid tuple ** */
  1506. if (estate->es_result_relation_info != NULL &&
  1507. estate->es_result_relation_info->ri_RangeTableIndex == rti)
  1508. relation = estate->es_result_relation_info->ri_RelationDesc;
  1509. else
  1510. {
  1511. List    *l;
  1512. foreach(l, estate->es_rowMark)
  1513. {
  1514. if (((execRowMark *) lfirst(l))->rti == rti)
  1515. break;
  1516. }
  1517. relation = ((execRowMark *) lfirst(l))->relation;
  1518. }
  1519. tuple.t_self = *tid;
  1520. for (;;)
  1521. {
  1522. heap_fetch(relation, SnapshotDirty, &tuple, &buffer);
  1523. if (tuple.t_data != NULL)
  1524. {
  1525. TransactionId xwait = SnapshotDirty->xmax;
  1526. if (TransactionIdIsValid(SnapshotDirty->xmin))
  1527. {
  1528. elog(NOTICE, "EvalPlanQual: t_xmin is uncommitted ?!");
  1529. Assert(!TransactionIdIsValid(SnapshotDirty->xmin));
  1530. elog(ERROR, "Aborting this transaction");
  1531. }
  1532. /*
  1533.  * If tuple is being updated by other transaction then we have
  1534.  * to wait for its commit/abort.
  1535.  */
  1536. if (TransactionIdIsValid(xwait))
  1537. {
  1538. ReleaseBuffer(buffer);
  1539. XactLockTableWait(xwait);
  1540. continue;
  1541. }
  1542. /*
  1543.  * Nice! We got tuple - now copy it.
  1544.  */
  1545. if (epqstate->es_evTuple[epq->rti - 1] != NULL)
  1546. pfree(epqstate->es_evTuple[epq->rti - 1]);
  1547. epqstate->es_evTuple[epq->rti - 1] = heap_copytuple(&tuple);
  1548. ReleaseBuffer(buffer);
  1549. break;
  1550. }
  1551. /*
  1552.  * Ops! Invalid tuple. Have to check is it updated or deleted.
  1553.  * Note that it's possible to get invalid SnapshotDirty->tid if
  1554.  * tuple updated by this transaction. Have we to check this ?
  1555.  */
  1556. if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&
  1557. !(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))
  1558. {
  1559. tuple.t_self = SnapshotDirty->tid; /* updated ... */
  1560. continue;
  1561. }
  1562. /*
  1563.  * Deleted or updated by this transaction. Do not (re-)start
  1564.  * execution of this PQ. Continue previous PQ.
  1565.  */
  1566. oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
  1567. if (oldepq != NULL)
  1568. {
  1569. Assert(oldepq->rti != 0);
  1570. /* push current PQ to freePQ stack */
  1571. oldepq->free = epq;
  1572. epq = oldepq;
  1573. epqstate = &(epq->estate);
  1574. estate->es_evalPlanQual = (Pointer) epq;
  1575. }
  1576. else
  1577. {
  1578. epq->rti = 0; /* this is the first (oldest) */
  1579. estate->es_useEvalPlan = false; /* PQ - mark as free and      */
  1580. return (NULL); /* continue Query execution   */
  1581. }
  1582. }
  1583. if (estate->es_origPlan->nParamExec > 0)
  1584. memset(epqstate->es_param_exec_vals, 0,
  1585.    estate->es_origPlan->nParamExec * sizeof(ParamExecData));
  1586. memset(epqstate->es_evTupleNull, false,
  1587.    length(estate->es_range_table) * sizeof(bool));
  1588.     Assert(epqstate->es_tupleTable->next == 0);
  1589. ExecInitNode(epq->plan, epqstate, NULL);
  1590. /*
  1591.  * For UPDATE/DELETE we have to return tid of actual row we're
  1592.  * executing PQ for.
  1593.  */
  1594. *tid = tuple.t_self;
  1595. return (EvalPlanQualNext(estate));
  1596. }
  1597. static TupleTableSlot *
  1598. EvalPlanQualNext(EState *estate)
  1599. {
  1600. evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
  1601. EState    *epqstate = &(epq->estate);
  1602. evalPlanQual *oldepq;
  1603. TupleTableSlot *slot;
  1604. Assert(epq->rti != 0);
  1605. lpqnext:;
  1606. slot = ExecProcNode(epq->plan, epq->plan);
  1607. /*
  1608.  * No more tuples for this PQ. Continue previous one.
  1609.  */
  1610. if (TupIsNull(slot))
  1611. {
  1612. ExecEndNode(epq->plan, epq->plan);
  1613.     epqstate->es_tupleTable->next = 0;
  1614. pfree(epqstate->es_evTuple[epq->rti - 1]);
  1615. epqstate->es_evTuple[epq->rti - 1] = NULL;
  1616. /* pop old PQ from the stack */
  1617. oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
  1618. if (oldepq == (evalPlanQual *) NULL)
  1619. {
  1620. epq->rti = 0; /* this is the first (oldest) */
  1621. estate->es_useEvalPlan = false; /* PQ - mark as free and   */
  1622. return (NULL); /* continue Query execution   */
  1623. }
  1624. Assert(oldepq->rti != 0);
  1625. /* push current PQ to freePQ stack */
  1626. oldepq->free = epq;
  1627. epq = oldepq;
  1628. epqstate = &(epq->estate);
  1629. estate->es_evalPlanQual = (Pointer) epq;
  1630. goto lpqnext;
  1631. }
  1632. return (slot);
  1633. }