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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * execTuples.c
  4.  *   Routines dealing with the executor tuple tables. These are used to
  5.  *   ensure that the executor frees copies of tuples (made by
  6.  *   ExecTargetList) properly.
  7.  *
  8.  *   Routines dealing with the type information for tuples. Currently,
  9.  *   the type information for a tuple is an array of FormData_pg_attribute.
  10.  *   This information is needed by routines manipulating tuples
  11.  *   (getattribute, formtuple, etc.).
  12.  *
  13.  * Copyright (c) 1994, Regents of the University of California
  14.  *
  15.  *
  16.  * IDENTIFICATION
  17.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.25 1999/05/25 16:08:39 momjian Exp $
  18.  *
  19.  *-------------------------------------------------------------------------
  20.  */
  21. /*
  22.  * INTERFACE ROUTINES
  23.  *
  24.  *  TABLE CREATE/DELETE
  25.  * ExecCreateTupleTable - create a new tuple table
  26.  * ExecDestroyTupleTable - destroy a table
  27.  *
  28.  *  SLOT RESERVERATION
  29.  * ExecAllocTableSlot - find an available slot in the table
  30.  *
  31.  *  SLOT ACCESSORS
  32.  * ExecStoreTuple - store a tuple in the table
  33.  * ExecFetchTuple - fetch a tuple from the table
  34.  * ExecClearTuple - clear contents of a table slot
  35.  * ExecSlotPolicy - return slot's tuple pfree policy
  36.  * ExecSetSlotPolicy - diddle the slot policy
  37.  * ExecSlotDescriptor - type of tuple in a slot
  38.  * ExecSetSlotDescriptor - set a slot's tuple descriptor
  39.  * ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag
  40.  * ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once
  41.  * ExecSlotBuffer - return buffer of tuple in slot
  42.  * ExecSetSlotBuffer - set the buffer for tuple in slot
  43.  * ExecIncrSlotBufferRefcnt - bump the refcnt of the slot buffer(Macro)
  44.  *
  45.  *  SLOT STATUS PREDICATES
  46.  * TupIsNull - true when slot contains no tuple(Macro)
  47.  * ExecSlotDescriptorIsNew - true if we're now storing a different
  48.  *   type of tuple in a slot
  49.  *
  50.  *  CONVENIENCE INITIALIZATION ROUTINES
  51.  * ExecInitResultTupleSlot     convience routines to initialize
  52.  * ExecInitScanTupleSlot the various tuple slots for nodes
  53.  * ExecInitMarkedTupleSlot /  which store copies of tuples.
  54.  * ExecInitOuterTupleSlot    /
  55.  * ExecInitHashTupleSlot   /
  56.  *
  57.  *  old routines:
  58.  * ExecGetTupType - get type of tuple returned by this node
  59.  * ExecTypeFromTL - form a TupleDesc from a target list
  60.  *
  61.  *  EXAMPLE OF HOW TABLE ROUTINES WORK
  62.  * Suppose we have a query such as retrieve (EMP.name) and we have
  63.  * a single SeqScan node in the query plan.
  64.  *
  65.  * At ExecStart()
  66.  * ----------------
  67.  * - InitPlan() calls ExecCreateTupleTable() to create the tuple
  68.  *   table which will hold tuples processed by the executor.
  69.  *
  70.  * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
  71.  *   ExecInitResultTupleSlot() to reserve places in the tuple
  72.  *   table for the tuples returned by the access methods and the
  73.  *   tuples resulting from preforming target list projections.
  74.  *
  75.  * During ExecRun()
  76.  * ----------------
  77.  * - SeqNext() calls ExecStoreTuple() to place the tuple returned
  78.  *   by the access methods into the scan tuple slot.
  79.  *
  80.  * - ExecSeqScan() calls ExecStoreTuple() to take the result
  81.  *   tuple from ExecTargetList() and place it into the result tuple
  82.  *   slot.
  83.  *
  84.  * - ExecutePlan() calls ExecRetrieve() which gets the tuple out of
  85.  *   the slot passed to it by calling ExecFetchTuple().  this tuple
  86.  *   is then returned.
  87.  *
  88.  * At ExecEnd()
  89.  * ----------------
  90.  * - EndPlan() calls ExecDestroyTupleTable() to clean up any remaining
  91.  *   tuples left over from executing the query.
  92.  *
  93.  * The important thing to watch in the executor code is how pointers
  94.  * to the slots containing tuples are passed instead of the tuples
  95.  * themselves.  This facilitates the communication of related information
  96.  * (such as whether or not a tuple should be pfreed, what buffer contains
  97.  * this tuple, the tuple's tuple descriptor, etc).   Note that much of
  98.  * this information is also kept in the ExprContext of each node.
  99.  * Soon the executor will be redesigned and ExprContext's will contain
  100.  * only slot pointers.  -cim 3/14/91
  101.  *
  102.  *  NOTES
  103.  * The tuple table stuff is relatively new, put here to alleviate
  104.  * the process growth problems in the executor.  The other routines
  105.  * are old (from the original lisp system) and may someday become
  106.  * obsolete.  -cim 6/23/90
  107.  *
  108.  * In the implementation of nested-dot queries such as
  109.  * "retrieve (EMP.hobbies.all)", a single scan may return tuples
  110.  * of many types, so now we return pointers to tuple descriptors
  111.  * along with tuples returned via the tuple table.  This means
  112.  * we now have a bunch of routines to diddle the slot descriptors
  113.  * too.  -cim 1/18/90
  114.  *
  115.  * The tuple table stuff depends on the executor/tuptable.h macros,
  116.  * and the TupleTableSlot node in execnodes.h.
  117.  *
  118.  */
  119. #include <string.h>
  120. #include "postgres.h"
  121. #include "executor/executor.h"
  122. #undef ExecStoreTuple
  123. #include "access/tupdesc.h"
  124. #include "catalog/pg_type.h"
  125. #include "parser/parse_type.h"
  126. #include "storage/bufmgr.h"
  127. #include "utils/palloc.h"
  128. #include "utils/lsyscache.h"
  129. static TupleTableSlot *NodeGetResultTupleSlot(Plan *node);
  130. /* ----------------------------------------------------------------
  131.  *   tuple table create/delete functions
  132.  * ----------------------------------------------------------------
  133.  */
  134. /* --------------------------------
  135.  * ExecCreateTupleTable
  136.  *
  137.  * This creates a new tuple table of the specified initial
  138.  * size.  If the size is insufficient, ExecAllocTableSlot()
  139.  * will grow the table as necessary.
  140.  *
  141.  * This should be used by InitPlan() to allocate the table.
  142.  * The table's address will be stored in the EState structure.
  143.  * --------------------------------
  144.  */
  145. TupleTable /* return: address of table */
  146. ExecCreateTupleTable(int initialSize) /* initial number of slots in
  147.  * table */
  148. {
  149. TupleTable newtable; /* newly allocated table */
  150. TupleTableSlot *array; /* newly allocated slot array */
  151. /* ----------------
  152.  * sanity checks
  153.  * ----------------
  154.  */
  155. Assert(initialSize >= 1);
  156. /* ----------------
  157.  * Now allocate our new table along with space for the pointers
  158.  * to the tuples.
  159.  */
  160. newtable = (TupleTable) palloc(sizeof(TupleTableData));
  161. array = (TupleTableSlot *) palloc(initialSize * sizeof(TupleTableSlot));
  162. /* ----------------
  163.  * clean out the slots we just allocated
  164.  * ----------------
  165.  */
  166. MemSet(array, 0, initialSize * sizeof(TupleTableSlot));
  167. /* ----------------
  168.  * initialize the new table and return it to the caller.
  169.  * ----------------
  170.  */
  171. newtable->size = initialSize;
  172. newtable->next = 0;
  173. newtable->array = array;
  174. return newtable;
  175. }
  176. /* --------------------------------
  177.  * ExecDestroyTupleTable
  178.  *
  179.  * This pfrees the storage assigned to the tuple table and
  180.  * optionally pfrees the contents of the table also.
  181.  * It is expected that this routine be called by EndPlan().
  182.  * --------------------------------
  183.  */
  184. void
  185. ExecDestroyTupleTable(TupleTable table, /* tuple table */
  186.   bool shouldFree) /* true if we should free slot
  187.  * contents */
  188. {
  189. int next; /* next avaliable slot */
  190. TupleTableSlot *array; /* start of table array */
  191. int i; /* counter */
  192. /* ----------------
  193.  * sanity checks
  194.  * ----------------
  195.  */
  196. Assert(table != NULL);
  197. /* ----------------
  198.  * get information from the table
  199.  * ----------------
  200.  */
  201. array = table->array;
  202. next = table->next;
  203. /* ----------------
  204.  * first free all the valid pointers in the tuple array
  205.  * if that's what the caller wants..
  206.  *
  207.  * Note: we do nothing about the Buffer and Tuple Descriptor's
  208.  * we store in the slots. This may have to change (ex: we should
  209.  * probably worry about pfreeing tuple descs too) -cim 3/14/91
  210.  * ----------------
  211.  */
  212. if (shouldFree)
  213. for (i = 0; i < next; i++)
  214. {
  215. TupleTableSlot slot;
  216. HeapTuple tuple;
  217. slot = array[i];
  218. tuple = slot.val;
  219. if (tuple != NULL)
  220. {
  221. slot.val = (HeapTuple) NULL;
  222. if (slot.ttc_shouldFree)
  223. {
  224. /* ----------------
  225.  * since a tuple may contain a pointer to
  226.  * lock information allocated along with the
  227.  * tuple, we have to be careful to free any
  228.  * rule locks also -cim 1/17/90
  229.  * ----------------
  230.  */
  231. pfree(tuple);
  232. }
  233. }
  234. }
  235. /* ----------------
  236.  * finally free the tuple array and the table itself.
  237.  * ----------------
  238.  */
  239. pfree(array);
  240. pfree(table);
  241. }
  242. /* ----------------------------------------------------------------
  243.  *   tuple table slot reservation functions
  244.  * ----------------------------------------------------------------
  245.  */
  246. /* --------------------------------
  247.  * ExecAllocTableSlot
  248.  *
  249.  * This routine is used to reserve slots in the table for
  250.  * use by the various plan nodes. It is expected to be
  251.  * called by the node init routines (ex: ExecInitNestLoop).
  252.  * once per slot needed by the node.  Not all nodes need
  253.  * slots (some just pass tuples around).
  254.  * --------------------------------
  255.  */
  256. TupleTableSlot * /* return: the slot allocated in the tuple
  257.  * table */
  258. ExecAllocTableSlot(TupleTable table)
  259. {
  260. int slotnum; /* new slot number */
  261. /* ----------------
  262.  * sanity checks
  263.  * ----------------
  264.  */
  265. Assert(table != NULL);
  266. /* ----------------
  267.  * if our table is full we have to allocate a larger
  268.  * size table.  Since ExecAllocTableSlot() is only called
  269.  * before the table is ever used to store tuples, we don't
  270.  * have to worry about the contents of the old table.
  271.  * If this changes, then we will have to preserve the contents.
  272.  * -cim 6/23/90
  273.  *
  274.  * Unfortunately, we *cannot* do this.  All of the nodes in
  275.  * the plan that have already initialized their slots will have
  276.  * pointers into _freed_ memory.  This leads to bad ends. We
  277.  * now count the number of slots we will need and create all the
  278.  * slots we will need ahead of time.  The if below should never
  279.  * happen now.  Give a WARN if it does.  -mer 4 Aug 1992
  280.  * ----------------
  281.  */
  282. if (table->next >= table->size)
  283. {
  284. /*
  285.  * int newsize = NewTableSize(table->size);
  286.  *
  287.  * pfree(table->array); table->array = (Pointer) palloc(newsize *
  288.  * TableSlotSize); bzero(table->array, newsize * TableSlotSize);
  289.  * table->size =  newsize;
  290.  */
  291. elog(NOTICE, "Plan requires more slots than are available");
  292. elog(ERROR, "send mail to your local executor guru to fix this");
  293. }
  294. /* ----------------
  295.  * at this point, space in the table is guaranteed so we
  296.  * reserve the next slot, initialize and return it.
  297.  * ----------------
  298.  */
  299. slotnum = table->next;
  300. table->next++;
  301. table->array[slotnum].type = T_TupleTableSlot;
  302. return &(table->array[slotnum]);
  303. }
  304. /* ----------------------------------------------------------------
  305.  *   tuple table slot accessor functions
  306.  * ----------------------------------------------------------------
  307.  */
  308. /* --------------------------------
  309.  * ExecStoreTuple
  310.  *
  311.  * This function is used to store a tuple into a specified
  312.  * slot in the tuple table.  Note: the only slots which should
  313.  * be called with shouldFree == false are those slots used to
  314.  * store tuples not allocated with pfree().  Currently the
  315.  * seqscan and indexscan nodes use this for the tuples returned
  316.  * by amgetattr, which are actually pointers onto disk pages.
  317.  * --------------------------------
  318.  */
  319. TupleTableSlot * /* return: slot passed */
  320. ExecStoreTuple(HeapTuple tuple, /* tuple to store */
  321.    TupleTableSlot *slot, /* slot in which to store tuple */
  322.    Buffer buffer, /* buffer associated with tuple */
  323.    bool shouldFree) /* true if we call pfree() when we gc. */
  324. {
  325. /* ----------------
  326.  * sanity checks
  327.  * ----------------
  328.  */
  329. Assert(slot != NULL);
  330. /* clear out the slot first */
  331. ExecClearTuple(slot);
  332. /* ----------------
  333.  * store the new tuple into the specified slot and
  334.  * return the slot into which we stored the tuple.
  335.  * ----------------
  336.  */
  337. slot->val = tuple;
  338. slot->ttc_buffer = buffer;
  339. slot->ttc_shouldFree = shouldFree;
  340. return slot;
  341. }
  342. /* --------------------------------
  343.  * ExecClearTuple
  344.  *
  345.  * This function is used to clear out a slot in the tuple table.
  346.  * --------------------------------
  347.  */
  348. TupleTableSlot * /* return: slot passed */
  349. ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
  350. {
  351. HeapTuple oldtuple; /* prior contents of slot */
  352. /* ----------------
  353.  * sanity checks
  354.  * ----------------
  355.  */
  356. Assert(slot != NULL);
  357. /* ----------------
  358.  * get information from the tuple table
  359.  * ----------------
  360.  */
  361. oldtuple = slot->val;
  362. /* ----------------
  363.  * free the old contents of the specified slot if necessary.
  364.  * ----------------
  365.  */
  366. if (slot->ttc_shouldFree && oldtuple != NULL)
  367. {
  368. /* ----------------
  369.  * since a tuple may contain a pointer to
  370.  * lock information allocated along with the
  371.  * tuple, we have to be careful to free any
  372.  * rule locks also -cim 1/17/90
  373.  * ----------------
  374.  */
  375. pfree(oldtuple);
  376. }
  377. /* ----------------
  378.  * store NULL into the specified slot and return the slot.
  379.  * - also set buffer to InvalidBuffer -cim 3/14/91
  380.  * ----------------
  381.  */
  382. slot->val = (HeapTuple) NULL;
  383. if (BufferIsValid(slot->ttc_buffer))
  384. ReleaseBuffer(slot->ttc_buffer);
  385. slot->ttc_buffer = InvalidBuffer;
  386. slot->ttc_shouldFree = true;
  387. return slot;
  388. }
  389. /* --------------------------------
  390.  * ExecSlotPolicy
  391.  *
  392.  * This function is used to get the call/don't call pfree
  393.  * setting of a slot. Most executor routines don't need this.
  394.  * It's only when you do tricky things like marking tuples for
  395.  * merge joins that you need to diddle the slot policy.
  396.  * --------------------------------
  397.  */
  398. #ifdef NOT_USED
  399. bool /* return: slot policy */
  400. ExecSlotPolicy(TupleTableSlot *slot) /* slot to inspect */
  401. {
  402. return slot->ttc_shouldFree;
  403. }
  404. /* --------------------------------
  405.  * ExecSetSlotPolicy
  406.  *
  407.  * This function is used to change the call/don't call pfree
  408.  * setting of a slot. Most executor routines don't need this.
  409.  * It's only when you do tricky things like marking tuples for
  410.  * merge joins that you need to diddle the slot policy.
  411.  * --------------------------------
  412.  */
  413. bool /* return: old slot policy */
  414. ExecSetSlotPolicy(TupleTableSlot *slot, /* slot to change */
  415.   bool shouldFree) /* true if we call pfree() when we
  416.  * gc. */
  417. {
  418. bool old_shouldFree = slot->ttc_shouldFree;
  419. slot->ttc_shouldFree = shouldFree;
  420. return old_shouldFree;
  421. }
  422. #endif
  423. /* --------------------------------
  424.  * ExecSlotDescriptor
  425.  *
  426.  * This function is used to get the tuple descriptor associated
  427.  * with the slot's tuple.
  428.  *
  429.  * Now a macro in tuptable.h  -mer 5 March 1992
  430.  * --------------------------------
  431.  */
  432. /* --------------------------------
  433.  * ExecSetSlotDescriptor
  434.  *
  435.  * This function is used to set the tuple descriptor associated
  436.  * with the slot's tuple.
  437.  * --------------------------------
  438.  */
  439. TupleDesc /* return: old slot tuple descriptor */
  440. ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
  441.   TupleDesc tupdesc) /* tuple descriptor */
  442. {
  443. TupleDesc old_tupdesc = slot->ttc_tupleDescriptor;
  444. slot->ttc_tupleDescriptor = tupdesc;
  445. return old_tupdesc;
  446. }
  447. /* --------------------------------
  448.  * ExecSetSlotDescriptorIsNew
  449.  *
  450.  * This function is used to change the setting of the "isNew" flag
  451.  * --------------------------------
  452.  */
  453. void
  454. ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, /* slot to change */
  455.    bool isNew) /* "isNew" setting */
  456. {
  457. slot->ttc_descIsNew = isNew;
  458. }
  459. /* --------------------------------
  460.  * ExecSetNewSlotDescriptor
  461.  *
  462.  * This function is used to set the tuple descriptor associated
  463.  * with the slot's tuple, and set the "isNew" flag at the same time.
  464.  * --------------------------------
  465.  */
  466. #ifdef NOT_USED
  467. TupleDesc /* return: old slot tuple descriptor */
  468. ExecSetNewSlotDescriptor(TupleTableSlot *slot, /* slot to change */
  469.  TupleDesc tupdesc) /* tuple descriptor */
  470. {
  471. TupleDesc old_tupdesc = slot->ttc_tupleDescriptor;
  472. slot->ttc_tupleDescriptor = tupdesc;
  473. slot->ttc_descIsNew = true;
  474. return old_tupdesc;
  475. }
  476. #endif
  477. /* --------------------------------
  478.  * ExecSlotBuffer
  479.  *
  480.  * This function is used to get the tuple descriptor associated
  481.  * with the slot's tuple.  Be very careful with this as it does not
  482.  * balance the reference counts.  If the buffer returned is stored
  483.  * someplace else, then also use ExecIncrSlotBufferRefcnt().
  484.  *
  485.  * Now a macro in tuptable.h
  486.  * --------------------------------
  487.  */
  488. /* --------------------------------
  489.  * ExecSetSlotBuffer
  490.  *
  491.  * This function is used to set the tuple descriptor associated
  492.  * with the slot's tuple.   Be very careful with this as it does not
  493.  * balance the reference counts.  If we're using this then we should
  494.  * also use ExecIncrSlotBufferRefcnt().
  495.  * --------------------------------
  496.  */
  497. #ifdef NOT_USED
  498. Buffer /* return: old slot buffer */
  499. ExecSetSlotBuffer(TupleTableSlot *slot, /* slot to change */
  500.   Buffer b) /* tuple descriptor */
  501. {
  502. Buffer oldb = slot->ttc_buffer;
  503. slot->ttc_buffer = b;
  504. return oldb;
  505. }
  506. #endif
  507. /* ----------------------------------------------------------------
  508.  *   tuple table slot status predicates
  509.  * ----------------------------------------------------------------
  510.  */
  511. /* --------------------------------
  512.  * ExecSlotDescriptorIsNew
  513.  *
  514.  * This function is used to check if the tuple descriptor
  515.  * associated with this slot has just changed.  ie: we are
  516.  * now storing a new type of tuple in this slot
  517.  * --------------------------------
  518.  */
  519. #ifdef NOT_USED
  520. bool /* return: descriptor "is new" */
  521. ExecSlotDescriptorIsNew(TupleTableSlot *slot) /* slot to inspect */
  522. {
  523. /*   bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot*) slot);
  524. return isNew; */
  525. return slot->ttc_descIsNew;
  526. }
  527. #endif
  528. /* ----------------------------------------------------------------
  529.  * convenience initialization routines
  530.  * ----------------------------------------------------------------
  531.  */
  532. /* --------------------------------
  533.  * ExecInit{Result,Scan,Raw,Marked,Outer,Hash}TupleSlot
  534.  *
  535.  * These are convenience routines to initialize the specfied slot
  536.  * in nodes inheriting the appropriate state.
  537.  * --------------------------------
  538.  */
  539. #define INIT_SLOT_DEFS 
  540. TupleTable    tupleTable; 
  541. TupleTableSlot*   slot
  542. #define INIT_SLOT_ALLOC 
  543. tupleTable = (TupleTable) estate->es_tupleTable; 
  544. slot =  ExecAllocTableSlot(tupleTable); 
  545. slot->val = (HeapTuple)NULL; 
  546. slot->ttc_shouldFree = true; 
  547. slot->ttc_tupleDescriptor = (TupleDesc)NULL; 
  548. slot->ttc_whichplan = -1;
  549. slot->ttc_descIsNew = true;
  550. /* ----------------
  551.  * ExecInitResultTupleSlot
  552.  * ----------------
  553.  */
  554. void
  555. ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
  556. {
  557. INIT_SLOT_DEFS;
  558. INIT_SLOT_ALLOC;
  559. commonstate->cs_ResultTupleSlot = (TupleTableSlot *) slot;
  560. }
  561. /* ----------------
  562.  * ExecInitScanTupleSlot
  563.  * ----------------
  564.  */
  565. void
  566. ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate)
  567. {
  568. INIT_SLOT_DEFS;
  569. INIT_SLOT_ALLOC;
  570. commonscanstate->css_ScanTupleSlot = (TupleTableSlot *) slot;
  571. }
  572. #ifdef NOT_USED
  573. /* ----------------
  574.  * ExecInitMarkedTupleSlot
  575.  * ----------------
  576.  */
  577. void
  578. ExecInitMarkedTupleSlot(EState *estate, MergeJoinState *mergestate)
  579. {
  580. INIT_SLOT_DEFS;
  581. INIT_SLOT_ALLOC;
  582. mergestate->mj_MarkedTupleSlot = (TupleTableSlot *) slot;
  583. }
  584. #endif
  585. /* ----------------
  586.  * ExecInitOuterTupleSlot
  587.  * ----------------
  588.  */
  589. void
  590. ExecInitOuterTupleSlot(EState *estate, HashJoinState *hashstate)
  591. {
  592. INIT_SLOT_DEFS;
  593. INIT_SLOT_ALLOC;
  594. hashstate->hj_OuterTupleSlot = slot;
  595. }
  596. /* ----------------
  597.  * ExecInitHashTupleSlot
  598.  * ----------------
  599.  */
  600. #ifdef NOT_USED
  601. void
  602. ExecInitHashTupleSlot(EState *estate, HashJoinState *hashstate)
  603. {
  604. INIT_SLOT_DEFS;
  605. INIT_SLOT_ALLOC;
  606. hashstate->hj_HashTupleSlot = slot;
  607. }
  608. #endif
  609. static TupleTableSlot *
  610. NodeGetResultTupleSlot(Plan *node)
  611. {
  612. TupleTableSlot *slot;
  613. switch (nodeTag(node))
  614. {
  615. case T_Result:
  616. {
  617. ResultState *resstate = ((Result *) node)->resstate;
  618. slot = resstate->cstate.cs_ResultTupleSlot;
  619. }
  620. break;
  621. case T_SeqScan:
  622. {
  623. CommonScanState *scanstate = ((SeqScan *) node)->scanstate;
  624. slot = scanstate->cstate.cs_ResultTupleSlot;
  625. }
  626. break;
  627. case T_NestLoop:
  628. {
  629. NestLoopState *nlstate = ((NestLoop *) node)->nlstate;
  630. slot = nlstate->jstate.cs_ResultTupleSlot;
  631. }
  632. break;
  633. case T_Append:
  634. {
  635. Append    *n = (Append *) node;
  636. AppendState *appendstate;
  637. List    *appendplans;
  638. int whichplan;
  639. Plan    *subplan;
  640. appendstate = n->appendstate;
  641. appendplans = n->appendplans;
  642. whichplan = appendstate->as_whichplan;
  643. subplan = (Plan *) nth(whichplan, appendplans);
  644. slot = NodeGetResultTupleSlot(subplan);
  645. break;
  646. }
  647. case T_IndexScan:
  648. {
  649. CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;
  650. slot = scanstate->cstate.cs_ResultTupleSlot;
  651. }
  652. break;
  653. case T_Material:
  654. {
  655. MaterialState *matstate = ((Material *) node)->matstate;
  656. slot = matstate->csstate.css_ScanTupleSlot;
  657. }
  658. break;
  659. case T_Sort:
  660. {
  661. SortState  *sortstate = ((Sort *) node)->sortstate;
  662. slot = sortstate->csstate.css_ScanTupleSlot;
  663. }
  664. break;
  665. case T_Agg:
  666. {
  667. AggState   *aggstate = ((Agg *) node)->aggstate;
  668. slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
  669. }
  670. break;
  671. case T_Group:
  672. {
  673. GroupState *grpstate = ((Group *) node)->grpstate;
  674. slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
  675. }
  676. break;
  677. case T_Hash:
  678. {
  679. HashState  *hashstate = ((Hash *) node)->hashstate;
  680. slot = hashstate->cstate.cs_ResultTupleSlot;
  681. }
  682. break;
  683. case T_Unique:
  684. {
  685. UniqueState *uniquestate = ((Unique *) node)->uniquestate;
  686. slot = uniquestate->cs_ResultTupleSlot;
  687. }
  688. break;
  689. case T_MergeJoin:
  690. {
  691. MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate;
  692. slot = mergestate->jstate.cs_ResultTupleSlot;
  693. }
  694. break;
  695. case T_HashJoin:
  696. {
  697. HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate;
  698. slot = hashjoinstate->jstate.cs_ResultTupleSlot;
  699. }
  700. break;
  701. default:
  702. /* ----------------
  703.  *   should never get here
  704.  * ----------------
  705.  */
  706. elog(ERROR, "NodeGetResultTupleSlot: node not yet supported: %d ",
  707.  nodeTag(node));
  708. return NULL;
  709. }
  710. return slot;
  711. }
  712. /* ----------------------------------------------------------------
  713.  * ExecGetTupType
  714.  *
  715.  * this gives you the tuple descriptor for tuples returned
  716.  * by this node.  I really wish I could ditch this routine,
  717.  * but since not all nodes store their type info in the same
  718.  * place, we have to do something special for each node type.
  719.  *
  720.  * Soon, the system will have to adapt to deal with changing
  721.  * tuple descriptors as we deal with dynamic tuple types
  722.  * being returned from procedure nodes.  Perhaps then this
  723.  * routine can be retired.  -cim 6/3/91
  724.  *
  725.  * old comments
  726.  * This routine just gets the type information out of the
  727.  * node's state.  If you already have a node's state, you
  728.  * can get this information directly, but this is a useful
  729.  * routine if you want to get the type information from
  730.  * the node's inner or outer subplan easily without having
  731.  * to inspect the subplan.. -cim 10/16/89
  732.  *
  733.  * ----------------------------------------------------------------
  734.  */
  735. TupleDesc
  736. ExecGetTupType(Plan *node)
  737. {
  738. TupleTableSlot *slot;
  739. TupleDesc tupType;
  740. if (node == NULL)
  741. return NULL;
  742. slot = NodeGetResultTupleSlot(node);
  743. tupType = slot->ttc_tupleDescriptor;
  744. return tupType;
  745. }
  746. /*
  747. TupleDesc
  748. ExecCopyTupType(TupleDesc td, int natts)
  749. {
  750. TupleDesc newTd;
  751. int i;
  752. newTd = CreateTemplateTupleDesc(natts);
  753. i = 0;
  754. while (i < natts)
  755. {
  756. newTd[i] = (Form_pg_attribute)palloc(sizeof(FormData_pg_attribute));
  757. memmove(newTd[i], td[i], sizeof(FormData_pg_attribute));
  758. i++;
  759. }
  760. return newTd;
  761. }
  762. */
  763. /* ----------------------------------------------------------------
  764.  * ExecTypeFromTL
  765.  *
  766.  * Currently there are about 4 different places where we create
  767.  * TupleDescriptors.  They should all be merged, or perhaps
  768.  * be rewritten to call BuildDesc().
  769.  *
  770.  * old comments
  771.  * Forms attribute type info from the target list in the node.
  772.  * It assumes all domains are individually specified in the target list.
  773.  * It fails if the target list contains something like Emp.all
  774.  * which represents all the attributes from EMP relation.
  775.  *
  776.  * Conditions:
  777.  * The inner and outer subtrees should be initialized because it
  778.  * might be necessary to know the type infos of the subtrees.
  779.  * ----------------------------------------------------------------
  780.  */
  781. TupleDesc
  782. ExecTypeFromTL(List *targetList)
  783. {
  784. List    *tlcdr;
  785. TupleDesc typeInfo;
  786. Resdom    *resdom;
  787. Oid restype;
  788. int len;
  789. /* ----------------
  790.  * examine targetlist - if empty then return NULL
  791.  * ----------------
  792.  */
  793. len = ExecTargetListLength(targetList);
  794. if (len == 0)
  795. return NULL;
  796. /* ----------------
  797.  * allocate a new typeInfo
  798.  * ----------------
  799.  */
  800. typeInfo = CreateTemplateTupleDesc(len);
  801. /* ----------------
  802.  * notes: get resdom from (resdom expr)
  803.  *   get_typbyval comes from src/lib/l-lisp/lsyscache.c
  804.  * ----------------
  805.  */
  806. tlcdr = targetList;
  807. while (tlcdr != NIL)
  808. {
  809. TargetEntry *tle = lfirst(tlcdr);
  810. if (tle->resdom != NULL)
  811. {
  812. resdom = tle->resdom;
  813. restype = resdom->restype;
  814. TupleDescInitEntry(typeInfo,
  815.    resdom->resno,
  816.    resdom->resname,
  817. /* fix for SELECT NULL ... */
  818.    (restype ? restype : UNKNOWNOID),
  819.    resdom->restypmod,
  820.    0,
  821.    false);
  822. /*
  823. ExecSetTypeInfo(resdom->resno - 1,
  824. typeInfo,
  825. (Oid) restype,
  826. resdom->resno,
  827. resdom->reslen,
  828. resdom->resname->data,
  829. get_typbyval(restype),
  830. get_typalign(restype));
  831. */
  832. }
  833. else
  834. {
  835. Resdom    *fjRes;
  836. List    *fjTlistP;
  837. List    *fjList = lfirst(tlcdr);
  838. #ifdef SETS_FIXED
  839. TargetEntry *tle;
  840. Fjoin    *fjNode = ((TargetEntry *) lfirst(fjList))->fjoin;
  841. tle = fjNode->fj_innerNode; /* ??? */
  842. #endif
  843. fjRes = tle->resdom;
  844. restype = fjRes->restype;
  845. TupleDescInitEntry(typeInfo,
  846.    fjRes->resno,
  847.    fjRes->resname,
  848.    restype,
  849.    fjRes->restypmod,
  850.    0,
  851.    false);
  852. /*
  853. ExecSetTypeInfo(fjRes->resno - 1,
  854. typeInfo,
  855. (Oid) restype,
  856. fjRes->resno,
  857. fjRes->reslen,
  858. (char *) fjRes->resname,
  859. get_typbyval(restype),
  860. get_typalign(restype));
  861. */
  862. foreach(fjTlistP, lnext(fjList))
  863. {
  864. TargetEntry *fjTle = lfirst(fjTlistP);
  865. fjRes = fjTle->resdom;
  866. TupleDescInitEntry(typeInfo,
  867.    fjRes->resno,
  868.    fjRes->resname,
  869.    restype,
  870.    fjRes->restypmod,
  871.    0,
  872.    false);
  873. /*
  874. ExecSetTypeInfo(fjRes->resno - 1,
  875. typeInfo,
  876. (Oid) fjRes->restype,
  877. fjRes->resno,
  878. fjRes->reslen,
  879. (char *) fjRes->resname,
  880. get_typbyval(fjRes->restype),
  881. get_typalign(fjRes->restype));
  882. */
  883. }
  884. }
  885. tlcdr = lnext(tlcdr);
  886. }
  887. return typeInfo;
  888. }