home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_tuples.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  34.4 KB  |  1,180 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    ex_tuples.c 
  4.  *    
  5.  *   DESCRIPTION
  6.  *    Routines dealing with the executor tuple tables.  These
  7.  *    are used to ensure that the executor frees copies of tuples
  8.  *    (made by ExecTargetList) properly.
  9.  *
  10.  *       Routines dealing with the type inforamtion for tuples.
  11.  *       Currently, the type information for a tuple is an array of
  12.  *       struct attribute. This information is needed by routines
  13.  *       manipulating tuples (getattribute, formtuple, etc.).
  14.  *    
  15.  *   INTERFACE ROUTINES
  16.  *
  17.  *   TABLE CREATE/DELETE
  18.  *    ExecCreateTupleTable    - create a new tuple table
  19.  *    ExecDestroyTupleTable    - destroy a table
  20.  *
  21.  *   SLOT RESERVERATION
  22.  *    ExecAllocTableSlot    - find an available slot in the table
  23.  *    ExecGetTableSlot    - get a slot corresponding to a table index
  24.  *
  25.  *   SLOT ACCESSORS
  26.  *    ExecStoreTuple        - store a tuple in the table
  27.  *    ExecFetchTuple        - fetch a tuple from the table
  28.  *    ExecClearTuple        - clear contents of a table slot
  29.  *    ExecSlotPolicy        - return slot's tuple pfree policy
  30.  *    ExecSetSlotPolicy    - diddle the slot policy
  31.  *    ExecSlotDescriptor    - type of tuple in a slot
  32.  *    ExecSetSlotDescriptor    - set a slot's tuple descriptor
  33.  *    ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag
  34.  *    ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once
  35.  *    ExecSlotBuffer        - return buffer of tuple in slot
  36.  *    ExecSetSlotBuffer    - set the buffer for tuple in slot
  37.  *    ExecIncrSlotBufferRefcnt - bump the refcnt of the slot buffer
  38.  *
  39.  *   SLOT STATUS PREDICATES
  40.  *    ExecNullSlot        - true when slot contains no tuple
  41.  *    ExecSlotDescriptorIsNew    - true if we're now storing a different
  42.  *                  type of tuple in a slot
  43.  *
  44.  *   CONVENIENCE INITIALIZATION ROUTINES
  45.  *    ExecInitResultTupleSlot    \    convience routines to initialize
  46.  *    ExecInitScanTupleSlot       \      the various tuple slots for nodes
  47.  *    ExecInitRawTupleSlot        \     which store copies of tuples.
  48.  *    ExecInitMarkedTupleSlot      /      
  49.  *    ExecInitOuterTupleSlot      /      
  50.  *    ExecInitHashTupleSlot /      
  51.  *
  52.  *   old routines:
  53.  *       ExecGetTupType         - get type of tuple returned by this node
  54.  *       ExecTypeFromTL       - form a TupleDescriptor from a target list
  55.  *
  56.  *   EXAMPLE OF HOW TABLE ROUTINES WORK
  57.  *    Suppose we have a query such as retrieve (EMP.name) and we have
  58.  *    a single SeqScan node in the query plan.
  59.  *
  60.  *    At ExecMain(EXEC_START)
  61.  *     ----------------
  62.  *    - InitPlan() calls ExecCreateTupleTable() to create the tuple
  63.  *      table which will hold tuples processed by the executor.
  64.  *
  65.  *    - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
  66.  *      ExecInitResultTupleSlot() to reserve places in the tuple
  67.  *      table for the tuples returned by the access methods and the
  68.  *      tuples resulting from preforming target list projections.
  69.  *
  70.  *    During ExecMain(EXEC_RUN)
  71.  *     ----------------
  72.  *    - SeqNext() calls ExecStoreTuple() to place the tuple returned
  73.  *      by the access methods into the scan tuple slot.
  74.  *
  75.  *    - ExecProcSeqScan() calls ExecStoreTuple() to take the result
  76.  *      tuple from ExecTargetList() and place it into the result tuple
  77.  *      slot.
  78.  *
  79.  *    - ExecutePlan() calls ExecRetrieve() which gets the tuple out of
  80.  *      the slot passed to it by calling ExecFetchTuple().  this tuple
  81.  *      is then returned.
  82.  *
  83.  *    At ExecMain(EXEC_END)
  84.  *     ----------------
  85.  *    - EndPlan() calls ExecDestroyTupleTable() to clean up any remaining
  86.  *      tuples left over from executing the query.
  87.  *
  88.  *    The important thing to watch in the executor code is how pointers
  89.  *    to the slots containing tuples are passed instead of the tuples
  90.  *    themselves.  This facilitates the communication of related information
  91.  *    (such as whether or not a tuple should be pfreed, what buffer contains
  92.  *    this tuple, the tuple's tuple descriptor, etc).   Note that much of
  93.  *    this information is also kept in the ExprContext of each node.
  94.  *    Soon the executor will be redesigned and ExprContext's will contain
  95.  *    only slot pointers.  -cim 3/14/91
  96.  *
  97.  *   NOTES
  98.  *    The tuple table stuff is relatively new, put here to alleviate
  99.  *    the process growth problems in the executor.  The other routines
  100.  *    are old (from the original lisp system) and may someday become
  101.  *    obsolete.  -cim 6/23/90
  102.  *
  103.  *    In the implementation of nested-dot queries such as
  104.  *    "retrieve (EMP.hobbies.all)", a single scan may return tuples
  105.  *    of many types, so now we return pointers to tuple descriptors
  106.  *    along with tuples returned via the tuple table.  This means
  107.  *    we now have a bunch of routines to diddle the slot descriptors
  108.  *    too.  -cim 1/18/90
  109.  *
  110.  *    The tuple table stuff depends on the lib/H/executor/tuptable.h macros,
  111.  *    and the TupleTableSlot node in execnodes.h.
  112.  *
  113.  *   IDENTIFICATION
  114.  *    $Header: /private/postgres/src/executor/RCS/ex_tuples.c,v 1.17 1992/08/04 17:37:46 mer Exp $
  115.  * ----------------------------------------------------------------
  116.  */
  117.  
  118. #include "executor/executor.h"
  119. #undef ExecStoreTuple
  120.  
  121.  RcsId("$Header: /private/postgres/src/executor/RCS/ex_tuples.c,v 1.17 1992/08/04 17:37:46 mer Exp $");
  122.  
  123. /* ----------------------------------------------------------------
  124.  *          tuple table create/delete functions
  125.  * ----------------------------------------------------------------
  126.  */
  127. /* --------------------------------
  128.  *    ExecCreateTupleTable
  129.  *
  130.  *    This creates a new tuple table of the specified initial
  131.  *    size.  If the size is insufficient, ExecAllocTableSlot()
  132.  *    will grow the table as necessary.
  133.  *
  134.  *    This should be used by InitPlan() to allocate the table.
  135.  *    The table's address would then be stored somewhere
  136.  *    in the EState structure.
  137.  * --------------------------------
  138.  */
  139. TupleTable            /* return: address of table */
  140. ExecCreateTupleTable(initialSize)
  141.     int        initialSize;    /* initial number of slots in table */
  142. {
  143.     TupleTable    newtable;    /* newly allocated table */
  144.     Pointer    array;        /* newly allocated table array */
  145.  
  146.     /* ----------------
  147.      *    sanity checks
  148.      * ----------------
  149.      */
  150.     Assert(initialSize >= 1);
  151.     
  152.     /* ----------------
  153.      *    Now allocate our new table along with space for the pointers
  154.      *    to the tuples.  Note: our array is actually an array of
  155.      *  TupleTableCells (which is a subclass of LispValue).
  156.      *  This is for 2 reasons:  1) there's lots of code that expects
  157.      *  tuples to be returned "inside" lispCons cells and 2) the cdr
  158.      *  field may one day be useful.
  159.      *  -cim 6/23/90
  160.      * ----------------
  161.      */
  162.     newtable = (TupleTable) palloc(sizeof(TupleTableData));
  163.     array    = (Pointer)    palloc(initialSize * TableSlotSize);
  164.  
  165.     /* ----------------
  166.      *    clean out the slots we just allocated
  167.      * ----------------
  168.      */
  169.     bzero(array, initialSize * TableSlotSize);
  170.     
  171.     /* ----------------
  172.      *    initialize the new table and return it to the caller.
  173.      * ----------------
  174.      */
  175.     newtable->size =    initialSize;
  176.     newtable->next =    0;
  177.     newtable->array =     array;
  178.  
  179.     return newtable;
  180. }
  181.  
  182. /* --------------------------------
  183.  *    ExecDestroyTupleTable
  184.  *
  185.  *    This pfrees the storage assigned to the tuple table and
  186.  *    optionally pfrees the contents of the table also.  
  187.  *    It is expected that this routine be called by EndPlan().
  188.  * --------------------------------
  189.  */
  190. void
  191. ExecDestroyTupleTable(table, shouldFree)
  192.     TupleTable    table;        /* tuple table */
  193.     bool    shouldFree;    /* true if we should free slot contents */
  194. {
  195.     int        next;        /* next avaliable slot */
  196.     Pointer    array;        /* start of table array */
  197.     int        i;        /* counter */
  198.  
  199.     /* ----------------
  200.      *    sanity checks
  201.      * ----------------
  202.      */
  203.     Assert(table != NULL);
  204.     
  205.     /* ----------------
  206.      *    get information from the table
  207.      * ----------------
  208.      */
  209.     array = table->array;
  210.     next =  table->next;
  211.               
  212.     /* ----------------
  213.      *    first free all the valid pointers in the tuple array
  214.      *  if that's what the caller wants..
  215.      *
  216.      *    Note: we do nothing about the Buffer and Tuple Descriptor's
  217.      *  we store in the slots.  This may have to change (ex: we should
  218.      *  probably worry about pfreeing tuple descs too) -cim 3/14/91
  219.      * ----------------
  220.      */
  221.     if (shouldFree)
  222.     for (i = 0; i < next; i++) {
  223.         Pointer    slot;
  224.         Pointer    tuple;
  225.  
  226.         slot =  TableSlot(array, i);
  227.         tuple = SlotContents(slot);
  228.     
  229.         if (tuple != NULL) {
  230.         SetSlotContents(slot, NULL);
  231.         if (SlotShouldFree((TupleTableSlot) slot)) {
  232.             /* ----------------
  233.              *    since a tuple may contain a pointer to
  234.              *  lock information allocated along with the
  235.              *  tuple, we have to be careful to free any
  236.              *  rule locks also -cim 1/17/90
  237.              * ----------------
  238.              */
  239.             HeapTupleFreeRuleLock(tuple);
  240.             pfree(tuple);
  241.         }
  242.         }
  243.     }
  244.  
  245.     /* ----------------
  246.      *    finally free the tuple array and the table itself.
  247.      * ----------------
  248.      */
  249.     pfree(array);
  250.     pfree(table);
  251.     
  252. }
  253.  
  254.  
  255. /* ----------------------------------------------------------------
  256.  *          tuple table slot reservation functions
  257.  * ----------------------------------------------------------------
  258.  */
  259. /* --------------------------------
  260.  *    ExecAllocTableSlot
  261.  *
  262.  *    This routine is used to reserve slots in the table for
  263.  *    use by the various plan nodes.  It is expected to be
  264.  *    called by the node init routines (ex: ExecInitNestLoop).
  265.  *    once per slot needed by the node.  Not all nodes need
  266.  *    slots (some just pass tuples around).
  267.  * --------------------------------
  268.  */
  269. int                 /* return: index into tuple table */
  270. ExecAllocTableSlot(table)
  271.     TupleTable    table;        /* tuple table */
  272. {
  273.     int    slotnum;        /* new slot number (returned) */
  274.     
  275.     /* ----------------
  276.      *    sanity checks
  277.      * ----------------
  278.      */
  279.     Assert(table != NULL);
  280.  
  281.     /* ----------------
  282.      *    if our table is full we have to allocate a larger
  283.      *    size table.  Since ExecAllocTableSlot() is only called
  284.      *  before the table is ever used to store tuples, we don't
  285.      *  have to worry about the contents of the old table.
  286.      *  If this changes, then we will have to preserve the contents.
  287.      *  -cim 6/23/90
  288.      *
  289.      *  Unfortunately, we *cannot* do this.  All of the nodes in
  290.      *  the plan that have already initialized their slots will have
  291.      *  pointers into _freed_ memory.  This leads to bad ends.  We
  292.      *  now count the number of slots we will need and create all the
  293.      *  slots we will need ahead of time.  The if below should never
  294.      *  happen now.  Give a WARN if it does.  -mer 4 Aug 1992
  295.      * ----------------
  296.      */
  297.     if (table->next >= table->size) {
  298.     /*
  299.      * int newsize = NewTableSize(table->size);
  300.      *
  301.      * pfree(table->array);
  302.      * table->array = (Pointer) palloc(newsize * TableSlotSize);
  303.      * bzero(table->array, newsize * TableSlotSize);
  304.      * table->size =  newsize;
  305.      */
  306.     elog(NOTICE, "Plan requires more slots than are available");
  307.     elog(WARN, "send mail to your local executor guru to fix this");
  308.     }
  309.  
  310.     /* ----------------
  311.      *    at this point, space in the table is guaranteed so we
  312.      *  reserve the next slot, initialize and return it.
  313.      * ----------------
  314.      */
  315.     slotnum = table->next;
  316.     table->next++;
  317.  
  318.     InitSlot(ExecGetTableSlot(table, slotnum));
  319.     return slotnum;
  320. }
  321.  
  322. /* --------------------------------
  323.  *    ExecGetTableSlot
  324.  *
  325.  *    This routine is used to get the slot (an address) corresponding
  326.  *    to a slot number (an index) for the specified tuple table.
  327.  * --------------------------------
  328.  */
  329. Pointer             /* return: address of slot containing tuple */
  330. ExecGetTableSlot(table, slotnum)
  331.     TupleTable    table;        /* table */
  332.     int        slotnum;    /* number of slot */
  333. {
  334.     Pointer    slot;        /* slot corresponding to slotnum in table */
  335.     
  336.     /* ----------------
  337.      *    sanity checks
  338.      * ----------------
  339.      */
  340.     Assert(table != NULL);
  341.     Assert(slotnum >= 0 && slotnum < table->next);
  342.  
  343.     /* ----------------
  344.      *    get information from the tuple table and return it.
  345.      * ----------------
  346.      */
  347.     slot = TableSlot(table->array, slotnum);    
  348.  
  349.     return slot;
  350. }
  351.  
  352. /* ----------------------------------------------------------------
  353.  *          tuple table slot accessor functions
  354.  * ----------------------------------------------------------------
  355.  */
  356.  
  357. /* --------------------------------
  358.  *    ExecStoreTuple
  359.  *
  360.  *    This function is used to store a tuple into a specified
  361.  *    slot in the tuple table.  Note: the only slots which should
  362.  *    be called with shouldFree == false are those slots used to
  363.  *    store tuples not allocated with pfree().  Currently the
  364.  *    seqscan and indexscan nodes use this for the tuples returned
  365.  *    by amgetattr, which are actually pointers onto disk pages.
  366.  * --------------------------------
  367.  */
  368. Pointer             /* return: slot passed */
  369. ExecStoreTuple(tuple, slot, buffer, shouldFree)
  370.     Pointer     tuple;        /* tuple to store */
  371.     Pointer    slot;        /* slot in which to store tuple */
  372.     Buffer    buffer;        /* buffer associated with tuple */
  373.     bool    shouldFree;    /* true if we call pfree() when we gc. */
  374. {
  375.     Pointer     oldtuple;    /* prior contents of slot */
  376.     
  377.     /* ----------------
  378.      *    sanity checks
  379.      * ----------------
  380.      */
  381.     Assert(slot != NULL);
  382.     
  383.     /* ----------------
  384.      *    get information from the tuple table
  385.      * ----------------
  386.      */
  387.     oldtuple =     SlotContents(slot);
  388.  
  389.     /* ----------------
  390.      *    free the old contents of the specified slot if necessary.
  391.      * ----------------
  392.      */
  393.     if (SlotShouldFree((TupleTableSlot) slot) && oldtuple != NULL) {
  394.     /* ----------------
  395.      *  since a tuple may contain a pointer to
  396.      *  lock information allocated along with the
  397.      *  tuple, we have to be careful to free any
  398.      *  rule locks also -cim 1/17/90
  399.      * ----------------
  400.      */
  401.     HeapTupleFreeRuleLock(oldtuple);
  402.     pfree(oldtuple);
  403.     }
  404.  
  405.     /* ----------------
  406.      *  if we have a buffer pinned, release it before stomping on it.
  407.      * ----------------
  408.      */
  409.     if (BufferIsValid(SlotBuffer((TupleTableSlot) slot)))
  410.     ReleaseBuffer(SlotBuffer((TupleTableSlot) slot));
  411.  
  412.     /* ----------------
  413.      *    store the new tuple into the specified slot and
  414.      *  return the slot into which we stored the tuple.
  415.      * ----------------
  416.      */
  417.     SetSlotContents((TupleTableSlot) slot, tuple);
  418.     SetSlotBuffer((TupleTableSlot) slot, buffer);
  419.     SetSlotShouldFree((TupleTableSlot) slot, shouldFree);
  420.  
  421.     return slot;
  422. }
  423.  
  424. Pointer             /* return: slot passed */
  425. ExecStoreTupleDebug(file, line, tuple, slot, buffer, shouldFree)
  426.     String    file;        /* filename */
  427.     int        line;        /* line number */
  428.     Pointer     tuple;        /* tuple to store */
  429.     Pointer    slot;        /* slot in which to store tuple */
  430.     Buffer    buffer;        /* buffer associated with tuple */
  431.     bool    shouldFree;    /* true if we call pfree() when we gc. */
  432. {
  433.     printf(":EST f %s l %d t 0x%x s 0x%x b %d sf %d\n",
  434.        file, line, tuple, slot, buffer, shouldFree);
  435.     return 
  436.     ExecStoreTuple(tuple, slot, buffer, shouldFree);
  437. }
  438.  
  439. /* --------------------------------
  440.  *    ExecFetchTuple
  441.  *
  442.  *    This function is used to get the heap tuple out of
  443.  *    a slot in the tuple table.
  444.  * --------------------------------
  445.  *
  446.  * Now a macro in tuptable.h  -mer 5 March 1992
  447.  */
  448.  
  449. /* --------------------------------
  450.  *    ExecClearTuple
  451.  *
  452.  *    This function is used to clear out a slot in the tuple table.
  453.  * --------------------------------
  454.  */
  455. Pointer             /* return: slot passed */
  456. ExecClearTuple(slot)
  457.     Pointer    slot;        /* slot in which to store tuple */
  458. {
  459.     Pointer     oldtuple;    /* prior contents of slot */
  460.     
  461.     /* ----------------
  462.      *    sanity checks
  463.      * ----------------
  464.      */
  465.     Assert(slot != NULL);
  466.  
  467.     /* ----------------
  468.      *    get information from the tuple table
  469.      * ----------------
  470.      */
  471.     oldtuple =     SlotContents(slot);
  472.  
  473.     /* ----------------
  474.      *    free the old contents of the specified slot if necessary.
  475.      * ----------------
  476.      */
  477.     if (SlotShouldFree((TupleTableSlot) slot) && oldtuple != NULL) {
  478.     /* ----------------
  479.      *  since a tuple may contain a pointer to
  480.      *  lock information allocated along with the
  481.      *  tuple, we have to be careful to free any
  482.      *  rule locks also -cim 1/17/90
  483.      * ----------------
  484.      */
  485.     HeapTupleFreeRuleLock(oldtuple);
  486.     pfree(oldtuple);
  487.     }
  488.  
  489.     /* ----------------
  490.      *    store NULL into the specified slot and return the slot.
  491.      *  - also set buffer to InvalidBuffer -cim 3/14/91
  492.      * ----------------
  493.      */
  494.     SetSlotContents(slot, NULL);
  495.  
  496.     if (BufferIsValid(SlotBuffer((TupleTableSlot) slot)))
  497.     ReleaseBuffer(SlotBuffer((TupleTableSlot) slot));
  498.     
  499.     SetSlotBuffer((TupleTableSlot) slot, InvalidBuffer);
  500.     SetSlotShouldFree((TupleTableSlot) slot, true);
  501.  
  502.     return slot;
  503. }
  504.  
  505.  
  506. /* --------------------------------
  507.  *    ExecSlotPolicy
  508.  *
  509.  *    This function is used to get the call/don't call pfree
  510.  *    setting of a slot.  Most executor routines don't need this.
  511.  *    It's only when you do tricky things like marking tuples for
  512.  *    merge joins that you need to diddle the slot policy.
  513.  * --------------------------------
  514.  */
  515. bool                /* return: slot policy */
  516. ExecSlotPolicy(slot)
  517.     Pointer    slot;        /* slot to inspect */
  518. {
  519.     bool shouldFree = SlotShouldFree((TupleTableSlot) slot);
  520.     return shouldFree;
  521. }
  522.  
  523. /* --------------------------------
  524.  *    ExecSetSlotPolicy
  525.  *
  526.  *    This function is used to change the call/don't call pfree
  527.  *    setting of a slot.  Most executor routines don't need this.
  528.  *    It's only when you do tricky things like marking tuples for
  529.  *    merge joins that you need to diddle the slot policy.
  530.  * --------------------------------
  531.  */
  532. bool                /* return: old slot policy */
  533. ExecSetSlotPolicy(slot, shouldFree)
  534.     Pointer    slot;        /* slot to change */
  535.     bool    shouldFree;    /* true if we call pfree() when we gc. */
  536. {
  537.     bool old_shouldFree = SlotShouldFree((TupleTableSlot) slot);
  538.     SetSlotShouldFree((TupleTableSlot) slot, shouldFree);
  539.  
  540.     return old_shouldFree;
  541. }
  542.  
  543. /* --------------------------------
  544.  *    ExecSlotDescriptor
  545.  *
  546.  *    This function is used to get the tuple descriptor associated
  547.  *    with the slot's tuple.
  548.  *
  549.  * Now a macro in tuptable.h  -mer 5 March 1992
  550.  * --------------------------------
  551.  */
  552.  
  553. /* --------------------------------
  554.  *    ExecSetSlotDescriptor
  555.  *
  556.  *    This function is used to set the tuple descriptor associated
  557.  *    with the slot's tuple.
  558.  * --------------------------------
  559.  */
  560. TupleDescriptor            /* return: old slot tuple descriptor */
  561. ExecSetSlotDescriptor(slot, tupdesc)
  562.     Pointer         slot;    /* slot to change */
  563.     TupleDescriptor  tupdesc;    /* tuple descriptor */
  564. {
  565.     TupleDescriptor  old_tupdesc = SlotTupleDescriptor((TupleTableSlot) slot);
  566.     SetSlotTupleDescriptor((TupleTableSlot) slot, tupdesc);
  567.     
  568.     return old_tupdesc;
  569. }
  570.  
  571. /* --------------------------------
  572.  *    ExecSetSlotDescriptorIsNew
  573.  *
  574.  *    This function is used to change the setting of the "isNew" flag
  575.  * --------------------------------
  576.  */
  577. void
  578. ExecSetSlotDescriptorIsNew(slot, isNew)
  579.     Pointer    slot;        /* slot to change */
  580.     bool    isNew;        /* "isNew" setting */
  581. {
  582.     SetSlotTupleDescriptorIsNew((TupleTableSlot) slot, isNew);
  583. }
  584.  
  585. /* --------------------------------
  586.  *    ExecSetNewSlotDescriptor
  587.  *
  588.  *    This function is used to set the tuple descriptor associated
  589.  *    with the slot's tuple, and set the "isNew" flag at the same time.
  590.  * --------------------------------
  591.  */
  592. TupleDescriptor            /* return: old slot tuple descriptor */
  593. ExecSetNewSlotDescriptor(slot, tupdesc)
  594.     Pointer         slot;    /* slot to change */
  595.     TupleDescriptor  tupdesc;    /* tuple descriptor */
  596. {
  597.     TupleDescriptor old_tupdesc = SlotTupleDescriptor((TupleTableSlot) slot);
  598.     SetSlotTupleDescriptor((TupleTableSlot) slot, tupdesc);
  599.     SetSlotTupleDescriptorIsNew((TupleTableSlot) slot, true);
  600.     
  601.     return old_tupdesc;
  602. }
  603.  
  604. /* --------------------------------
  605.  *    ExecSlotBuffer
  606.  *
  607.  *    This function is used to get the tuple descriptor associated
  608.  *    with the slot's tuple.  Be very careful with this as it does not
  609.  *    balance the reference counts.  If the buffer returned is stored
  610.  *    someplace else, then also use ExecIncrSlotBufferRefcnt().
  611.  *
  612.  * Now a macro in tuptable.h
  613.  * --------------------------------
  614.  */
  615.  
  616. /* --------------------------------
  617.  *    ExecSetSlotBuffer
  618.  *
  619.  *    This function is used to set the tuple descriptor associated
  620.  *    with the slot's tuple.   Be very careful with this as it does not
  621.  *    balance the reference counts.  If we're using this then we should
  622.  *    also use ExecIncrSlotBufferRefcnt().
  623.  * --------------------------------
  624.  */
  625. Buffer                /* return: old slot buffer */
  626. ExecSetSlotBuffer(slot, b)
  627.     Pointer slot;        /* slot to change */
  628.     Buffer  b;            /* tuple descriptor */
  629. {
  630.     Buffer oldb = SlotBuffer((TupleTableSlot) slot);
  631.     SetSlotBuffer((TupleTableSlot) slot, b);
  632.     
  633.     return oldb;
  634. }
  635.  
  636. /* --------------------------------
  637.  *    ExecIncrSlotBufferRefcnt
  638.  *
  639.  *    When we pass around buffers in the tuple table, we have to
  640.  *    be careful to increment reference counts appropriately.
  641.  *    This is used mainly in the mergejoin code.
  642.  * --------------------------------
  643.  */
  644. void
  645. ExecIncrSlotBufferRefcnt(slot)    
  646.     Pointer slot;        /* slot to bump refcnt */
  647. {
  648.     Buffer b = SlotBuffer((TupleTableSlot) slot);
  649.     if (BufferIsValid(b))
  650.     IncrBufferRefCount(b);
  651. }
  652.  
  653. /* ----------------------------------------------------------------
  654.  *          tuple table slot status predicates
  655.  * ----------------------------------------------------------------
  656.  */
  657.  
  658. /* ----------------
  659.  *    ExecNullSlot
  660.  *
  661.  *    This is used mainly to detect when there are no more
  662.  *    tuples to process.  The TupIsNull() macro calls this.
  663.  * ----------------
  664.  */
  665. bool                /* return: true if tuple in slot is NULL */
  666. ExecNullSlot(slot)
  667.     Pointer    slot;        /* slot to check */
  668. {
  669.     Pointer     tuple;        /* contents of slot (returned) */
  670.  
  671.     /* ----------------
  672.      *    if the slot itself is null then we return true
  673.      * ----------------
  674.      */
  675.     if (slot == NULL)
  676.     return true;
  677.     
  678.     /* ----------------
  679.      *    get information from the slot and return true or
  680.      *  false depending on the contents of the slot.
  681.      * ----------------
  682.      */
  683.     tuple =     SlotContents(slot);
  684.  
  685.     return
  686.     (tuple == NULL ? true : false);
  687. }
  688.  
  689. /* --------------------------------
  690.  *    ExecSlotDescriptorIsNew
  691.  *
  692.  *    This function is used to check if the tuple descriptor
  693.  *    associated with this slot has just changed.  ie: we are
  694.  *    now storing a new type of tuple in this slot
  695.  * --------------------------------
  696.  */
  697. bool                /* return: descriptor "is new" */
  698. ExecSlotDescriptorIsNew(slot)
  699.     Pointer    slot;        /* slot to inspect */
  700. {
  701.     bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot) slot);
  702.     return isNew;
  703. }
  704.  
  705. /* ----------------------------------------------------------------
  706.  *        convenience initialization routines 
  707.  * ----------------------------------------------------------------
  708.  */
  709. /* --------------------------------
  710.  *    ExecInit{Result,Scan,Raw,Marked,Outer,Hash}TupleSlot
  711.  *
  712.  *    These are convience routines to initialize the specfied slot
  713.  *    in nodes inheriting the appropriate state.
  714.  * --------------------------------
  715.  */
  716. #define INIT_SLOT_DEFS \
  717.     TupleTable     tupleTable; \
  718.     int        slotnum; \
  719.     Pointer       slot
  720.  
  721. #define INIT_SLOT_ALLOC \
  722.     tupleTable = (TupleTable) get_es_tupleTable(estate); \
  723.     slotnum =    ExecAllocTableSlot(tupleTable); \
  724.     slot =       ExecGetTableSlot(tupleTable, slotnum); \
  725.     SetSlotContents((TupleTableSlot) slot, NULL); \
  726.     SetSlotShouldFree((TupleTableSlot) slot, true); \
  727.     SetSlotTupleDescriptor((TupleTableSlot) slot, (TupleDescriptor) NULL); \
  728.     SetSlotExecTupDescriptor((TupleTableSlot) slot, (ExecTupDescriptor) NULL); \
  729.     SetSlotWhichPlan((TupleTableSlot) slot, -1); \
  730.     SetSlotTupleDescriptorIsNew((TupleTableSlot) slot, true)
  731.     
  732. /* ----------------
  733.  *    ExecInitResultTupleSlot
  734.  * ----------------
  735.  */
  736. void
  737. ExecInitResultTupleSlot(estate, commonstate)
  738.     EState     estate;
  739.     CommonState    commonstate;
  740. {
  741.     INIT_SLOT_DEFS;
  742.     INIT_SLOT_ALLOC;
  743.     set_cs_ResultTupleSlot(commonstate, (TupleTableSlot) slot);
  744. }
  745.  
  746. /* ----------------
  747.  *    ExecInitScanTupleSlot
  748.  * ----------------
  749.  */
  750. void
  751. ExecInitScanTupleSlot(estate, commonscanstate)
  752.     EState         estate;
  753.     CommonScanState    commonscanstate;
  754. {
  755.     INIT_SLOT_DEFS;
  756.     INIT_SLOT_ALLOC;
  757.     set_css_ScanTupleSlot(commonscanstate, (TupleTableSlot)slot);
  758. }
  759.  
  760. /* ----------------
  761.  *    ExecInitRawTupleSlot
  762.  * ----------------
  763.  */
  764. void
  765. ExecInitRawTupleSlot(estate, commonscanstate)
  766.     EState         estate;
  767.     CommonScanState    commonscanstate;
  768. {
  769.     INIT_SLOT_DEFS;
  770.     INIT_SLOT_ALLOC;
  771.     set_css_RawTupleSlot(commonscanstate, (TupleTableSlot)slot);
  772. }
  773.  
  774. /* ----------------
  775.  *    ExecInitMarkedTupleSlot
  776.  * ----------------
  777.  */
  778. void
  779. ExecInitMarkedTupleSlot(estate, mergestate)
  780.     EState         estate;
  781.     MergeJoinState    mergestate;
  782. {
  783.     INIT_SLOT_DEFS;
  784.     INIT_SLOT_ALLOC;
  785.     set_mj_MarkedTupleSlot(mergestate, (TupleTableSlot) slot);
  786. }
  787.  
  788. /* ----------------
  789.  *    ExecInitOuterTupleSlot
  790.  * ----------------
  791.  */
  792. void
  793. ExecInitOuterTupleSlot(estate, hashstate)
  794.     EState         estate;
  795.     HashJoinState    hashstate;
  796. {
  797.     INIT_SLOT_DEFS;
  798.     INIT_SLOT_ALLOC;
  799.     set_hj_OuterTupleSlot(hashstate,  slot);
  800. }
  801.  
  802. /* ----------------
  803.  *    ExecInitHashTupleSlot
  804.  * ----------------
  805.  */
  806. void
  807. ExecInitHashTupleSlot(estate, hashstate)
  808.     EState         estate;
  809.     HashJoinState    hashstate;
  810. {
  811.     INIT_SLOT_DEFS;
  812.     INIT_SLOT_ALLOC;
  813.     set_hj_HashTupleSlot(hashstate, slot);
  814. }
  815.  
  816. TupleTableSlot
  817. NodeGetResultTupleSlot(node)
  818. Plan node;
  819. {
  820.     TupleTableSlot slot;
  821.     union {
  822.     ResultState        resstate;
  823.     ScanState          scanstate;
  824.     NestLoopState      nlstate;
  825.     MaterialState    matstate;
  826.     SortState    sortstate;
  827.     AggState    aggstate;
  828.     HashState    hashstate;
  829.     UniqueState    uniquestate;
  830.     MergeJoinState     mergestate;
  831.     HashJoinState     hashjoinstate;
  832.     ScanTempState    scantempstate;
  833.     } s;
  834.  
  835.     switch(NodeType(node)) {
  836.     
  837.     case classTag(Result):
  838.     s.resstate =         get_resstate((Result) node);
  839.     slot =             get_cs_ResultTupleSlot(
  840.                                (CommonState)
  841.                                s.resstate);
  842.     break;
  843.     
  844.     case classTag(SeqScan):
  845.     s.scanstate =         get_scanstate((Scan) node);
  846.     slot =             get_cs_ResultTupleSlot((CommonState)
  847.                                s.scanstate);
  848.     break;
  849.     
  850.     case classTag(ScanTemps):
  851.     s.scantempstate =     get_scantempState((ScanTemps) node);
  852.     slot =             get_cs_ResultTupleSlot((CommonState)
  853.                                s.scantempstate);
  854.     break;
  855.  
  856.     case classTag(NestLoop):
  857.     s.nlstate =          get_nlstate((NestLoop) node);
  858.     slot =             get_cs_ResultTupleSlot((CommonState)
  859.                                s.nlstate);
  860.     break;
  861.        
  862.     case classTag(Append):
  863.     {
  864.         AppendState     unionstate;
  865.         List         unionplans;
  866.         int          whichplan;
  867.         Plan         subplan;
  868.         
  869.         unionstate =     get_unionstate((Append) node);
  870.         unionplans =     get_unionplans((Append) node);
  871.         whichplan =     get_as_whichplan(unionstate);
  872.       
  873.         subplan = (Plan) nth(whichplan, unionplans);
  874.         slot = NodeGetResultTupleSlot(subplan);
  875.         break;
  876.     }
  877.     
  878.     case classTag(IndexScan):
  879.     s.scanstate =         get_scanstate((Scan) node);
  880.     slot =          get_cs_ResultTupleSlot((CommonState)
  881.                                s.scanstate);
  882.     break;
  883.     
  884.     case classTag(Material):
  885.     s.matstate =         get_matstate((Material) node);
  886.     slot =             get_css_ScanTupleSlot((CommonScanState)
  887.                               s.matstate);
  888.     break;
  889.     
  890.     case classTag(Sort):
  891.     s.sortstate =         get_sortstate((Sort) node);
  892.     slot =             get_css_ScanTupleSlot((CommonScanState)
  893.                               s.sortstate);
  894.     break;
  895.         
  896.     case classTag(Agg):
  897.     s.aggstate =         get_aggstate((Agg) node);
  898.     slot =             get_cs_ResultTupleSlot((CommonState)
  899.                                s.aggstate);
  900.     break;
  901.  
  902.     case classTag(Hash):
  903.     s.hashstate =         get_hashstate((Hash) node);
  904.     slot =            get_cs_ResultTupleSlot((CommonState)
  905.                                s.hashstate);
  906.     break;
  907.         
  908.     case classTag(Unique):
  909.     s.uniquestate =     get_uniquestate((Unique) node);
  910.     slot =            get_cs_ResultTupleSlot((CommonState)
  911.                                s.uniquestate);
  912.     break;
  913.     
  914.     case classTag(MergeJoin):
  915.     s.mergestate =         get_mergestate((MergeJoin) node);
  916.     slot =            get_cs_ResultTupleSlot((CommonState)
  917.                                s.mergestate);
  918.     break;
  919.     
  920.     case classTag(HashJoin):
  921.     s.hashjoinstate =     get_hashjoinstate((HashJoin) node);
  922.     slot =            get_cs_ResultTupleSlot((CommonState)
  923.                                s.hashjoinstate);
  924.     break;
  925.  
  926.     default:
  927.     /* ----------------
  928.      *    should never get here
  929.      * ----------------
  930.      */
  931.     elog(DEBUG, "NodeGetResultTupleSlot: node not yet supported: %d ",
  932.          NodeGetTag(node));
  933.     
  934.     return NULL;
  935.     }
  936.     return slot;
  937. }
  938.  
  939. /* ----------------------------------------------------------------
  940.  *              old lisp support routines
  941.  * ----------------------------------------------------------------
  942.  */
  943. /* ----------------------------------------------------------------
  944.  *       ExecGetTupType
  945.  *
  946.  *    this gives you the tuple descriptor for tuples returned
  947.  *    by this node.  I really wish I could ditch this routine,
  948.  *    but since not all nodes store their type info in the same
  949.  *    place, we have to do something special for each node type.
  950.  *
  951.  *    Soon, the system will have to adapt to deal with changing
  952.  *    tuple descriptors as we deal with dynamic tuple types
  953.  *    being returned from procedure nodes.  Perhaps then this
  954.  *    routine can be retired.  -cim 6/3/91
  955.  *
  956.  * old comments
  957.  *    This routine just gets the type information out of the
  958.  *    node's state.  If you already have a node's state, you
  959.  *    can get this information directly, but this is a useful
  960.  *    routine if you want to get the type information from
  961.  *    the node's inner or outer subplan easily without having
  962.  *    to inspect the subplan.. -cim 10/16/89
  963.  *
  964.  *       Assume that for existential nodes, we get the targetlist out
  965.  *       of the right node's targetlist
  966.  * ----------------------------------------------------------------
  967.  */
  968.  
  969. TupleDescriptor
  970. ExecGetTupType(node) 
  971.     Plan node;
  972. {
  973.     TupleTableSlot    slot;
  974.     TupleDescriptor   tupType;
  975.     
  976.     if (node == NULL)
  977.     return NULL;
  978.  
  979.     slot = NodeGetResultTupleSlot(node);
  980.     tupType = ExecSlotDescriptor((Pointer) slot);
  981.     return tupType;
  982. }
  983.  
  984. TupleDescriptor
  985. ExecCopyTupType(td, natts) 
  986.     TupleDescriptor td;
  987.     int             natts;
  988. {
  989.     TupleDescriptor newTd;
  990.     int             i;
  991.  
  992.     newTd = CreateTemplateTupleDesc(natts);
  993.     i = 0;
  994.     while (i < natts)
  995.     {
  996.     newTd->data[i] =
  997.         (AttributeTupleForm)palloc( sizeof(AttributeTupleFormD) );
  998.     bcopy(td->data[i], newTd->data[i], sizeof(AttributeTupleFormD));
  999.     i++;
  1000.     }
  1001.     return newTd;
  1002. }
  1003.  
  1004. ExecTupDescriptor
  1005. ExecGetExecTupDesc(node) 
  1006.     Plan node;
  1007. {
  1008.     TupleTableSlot    slot;
  1009.     ExecTupDescriptor execTupDesc;
  1010.     
  1011.     if (node == NULL)
  1012.     return NULL;
  1013.  
  1014.     slot = NodeGetResultTupleSlot(node);
  1015.     execTupDesc = ExecSlotExecDescriptor(slot);
  1016.     return execTupDesc;
  1017. }
  1018.  
  1019. /* ----------------------------------------------------------------
  1020.  *       ExecTypeFromTL
  1021.  *       
  1022.  *    Currently there are about 4 different places where we create
  1023.  *    TupleDescriptors.  They should all be merged, or perhaps
  1024.  *    be rewritten to call BuildDesc().
  1025.  *       
  1026.  *  old comments
  1027.  *       Forms attribute type info from the target list in the node.
  1028.  *       It assumes all domains are individually specified in the target list.
  1029.  *       It fails if the target list contains something like Emp.all
  1030.  *       which represents all the attributes from EMP relation.
  1031.  *   
  1032.  *       Conditions:
  1033.  *           The inner and outer subtrees should be initialized because it
  1034.  *           might be necessary to know the type infos of the subtrees.
  1035.  * ----------------------------------------------------------------
  1036.  */
  1037. /**** xxref:
  1038.  *           ExecInitIndexScan
  1039.  *           ExecInitMergeJoin
  1040.  *           ExecInitNestLoop
  1041.  *           ExecInitResult
  1042.  *           ExecInitSeqScan
  1043.  ****/
  1044. TupleDescriptor
  1045. ExecTypeFromTL(targetList)
  1046.     List          targetList;
  1047. {
  1048.     List          tlcdr;
  1049.     TupleDescriptor     typeInfo;
  1050.     Resdom            resdom;
  1051.     ObjectId         restype;
  1052.     int          len;
  1053.    
  1054.    /* ----------------
  1055.     *  examine targetlist - if empty then return NULL
  1056.     * ----------------
  1057.     */
  1058.     len = ExecTargetListLength(targetList);
  1059.  
  1060.     if (len == 0)
  1061.     return NULL;
  1062.    
  1063.    /* ----------------
  1064.     *  allocate a new typeInfo
  1065.     * ----------------
  1066.     */
  1067.     typeInfo = ExecMakeTypeInfo(len);
  1068.     if (typeInfo == NULL)
  1069.     elog(DEBUG, "ExecTypeFromTL: ExecMakeTypeInfo returns null.");
  1070.  
  1071.    /* ----------------
  1072.     * notes: get resdom from (resdom expr)
  1073.     *        get_typbyval comes from src/lib/l-lisp/lsyscache.c
  1074.     * ----------------
  1075.     */
  1076.     tlcdr = targetList;
  1077.     while (! lispNullp(tlcdr)) {
  1078.     if (tl_is_resdom(CAR(tlcdr))) {
  1079.         resdom =  (Resdom) tl_resdom(CAR(tlcdr));
  1080.         restype = get_restype(resdom);
  1081.       
  1082.         ExecSetTypeInfo((int) get_resno(resdom) - 1,    /* index */
  1083.                 (struct attribute **) typeInfo, /* type info addr */
  1084.                 (ObjectId) restype,            /* type id */
  1085.                 (int) get_resno(resdom),        /* att num */
  1086.                 (int) get_reslen(resdom),        /* att len */
  1087.                 (char *) get_resname(resdom),   /* att name */
  1088.                 get_typbyval(restype));        /* att by val */
  1089.     }
  1090.     else {
  1091.         Resdom fjRes;
  1092.         List  fjTlistP;
  1093.         List  fjList = CAR(tlcdr);
  1094.         Fjoin fjNode = (Fjoin)tl_node(fjList);
  1095.  
  1096.         fjRes = (Resdom)tl_resdom(get_fj_innerNode(fjNode));
  1097.         restype = get_restype(fjRes);
  1098.  
  1099.         ExecSetTypeInfo(
  1100.             (int) get_resno(fjRes) - 1,        /* index */
  1101.             (struct attribute **) typeInfo,    /* addr of type info */
  1102.             (ObjectId) restype,               /* type id */
  1103.             (int) get_resno(fjRes),           /* att num */
  1104.             (int) get_reslen(fjRes),           /* att len */
  1105.             (char *) get_resname(fjRes),       /* att name */
  1106.             get_typbyval(restype));            /* att by val */
  1107.  
  1108.         foreach(fjTlistP, CDR(fjList)) {
  1109.         List fjTle = CAR(fjTlistP);
  1110.  
  1111.         fjRes = (Resdom)tl_resdom(fjTle);
  1112.         ExecSetTypeInfo(
  1113.               (int) get_resno(fjRes) - 1,        /* index */
  1114.               (struct attribute **) typeInfo,    /* addr of type info */
  1115.               (ObjectId) restype,         /* type id */
  1116.               (int) get_resno(fjRes),             /* att num */
  1117.               (int) get_reslen(fjRes),             /* att len */
  1118.               (char *) get_resname(fjRes),       /* att name */
  1119.               get_typbyval(get_restype(fjRes))); /* att by val */
  1120.  
  1121.         } /* foreach */
  1122.  
  1123.     }     /* else tl_is_resdom */
  1124.  
  1125.     tlcdr = CDR(tlcdr);
  1126.  
  1127.     } /* while (! lispNullp(tlcdr)) */
  1128.    
  1129.     return typeInfo;
  1130. }
  1131.  
  1132. /*
  1133.  * function to convert from an ExecTupDescriptor to a flat Tuple Descriptor
  1134.  */
  1135. TupleDescriptor
  1136. ExecTupDescToTupDesc(execTupDesc,len)
  1137. ExecTupDescriptor execTupDesc;
  1138. int len;
  1139. {
  1140.     int i, j;
  1141.     TupleDescriptor tupdesc;
  1142.     int tdlen;
  1143.     int count;
  1144.  
  1145.     tdlen = 0;
  1146.     for (i=0; i<len; i++)
  1147.     tdlen += execTupDesc->data[i]->len;
  1148.     tupdesc = CreateTemplateTupleDesc(tdlen);
  1149.     count = 0;
  1150.     for (i=0; i<len; i++) {
  1151.         for (j=0; j<execTupDesc->data[i]->len; j++) {
  1152.         tupdesc->data[count] = (AttributeTupleForm)
  1153.             palloc(sizeof(AttributeTupleFormD));
  1154.         bcopy(execTupDesc->data[i]->attdesc->data[j],
  1155.           tupdesc->data[count],
  1156.           sizeof(AttributeTupleFormD));
  1157.         tupdesc->data[count++]->attcacheoff = -1;
  1158.       }
  1159.       }
  1160.     return tupdesc;
  1161. }
  1162.  
  1163. /*
  1164.  * function to convert from a Tuple Descriptor to an ExecTupDescriptor
  1165.  */
  1166. ExecTupDescriptor
  1167. TupDescToExecTupDesc(tupDesc, len)
  1168. TupleDescriptor tupDesc;
  1169. int len;
  1170. {
  1171.     ExecTupDescriptor execTupDesc;
  1172.     int i;
  1173.  
  1174.     execTupDesc = ExecMakeExecTupDesc(len);
  1175.     for (i=0; i<len; i++) {
  1176.         execTupDesc->data[i] = MakeExecAttDesc(ATTVAL, 1, (TupleDescriptor)tupDesc->data[i]);
  1177.       }
  1178.     return execTupDesc;
  1179. }
  1180.