1 /*-------------------------------------------------------------------------
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.
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.).
13 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
14 * Portions Copyright (c) 1994, Regents of the University of California
18 * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.39 2000/09/12 21:06:48 tgl Exp $
20 *-------------------------------------------------------------------------
26 * ExecCreateTupleTable - create a new tuple table
27 * ExecDropTupleTable - destroy a table
30 * ExecAllocTableSlot - find an available slot in the table
33 * ExecStoreTuple - store a tuple in the table
34 * ExecFetchTuple - fetch a tuple from the table
35 * ExecClearTuple - clear contents of a table slot
36 * ExecSlotPolicy - return slot's tuple pfree policy
37 * ExecSetSlotPolicy - diddle the slot policy
38 * ExecSlotDescriptor - type of tuple in a slot
39 * ExecSetSlotDescriptor - set a slot's tuple descriptor
40 * ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag
41 * ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once
43 * SLOT STATUS PREDICATES
44 * TupIsNull - true when slot contains no tuple(Macro)
45 * ExecSlotDescriptorIsNew - true if we're now storing a different
46 * type of tuple in a slot
48 * CONVENIENCE INITIALIZATION ROUTINES
49 * ExecInitResultTupleSlot \ convenience routines to initialize
50 * ExecInitScanTupleSlot \ the various tuple slots for nodes
51 * ExecInitExtraTupleSlot / which store copies of tuples.
52 * ExecInitNullTupleSlot /
55 * ExecGetTupType - get type of tuple returned by this node
56 * ExecTypeFromTL - form a TupleDesc from a target list
58 * EXAMPLE OF HOW TABLE ROUTINES WORK
59 * Suppose we have a query such as retrieve (EMP.name) and we have
60 * a single SeqScan node in the query plan.
64 * - InitPlan() calls ExecCreateTupleTable() to create the tuple
65 * table which will hold tuples processed by the executor.
67 * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
68 * ExecInitResultTupleSlot() to reserve places in the tuple
69 * table for the tuples returned by the access methods and the
70 * tuples resulting from preforming target list projections.
74 * - SeqNext() calls ExecStoreTuple() to place the tuple returned
75 * by the access methods into the scan tuple slot.
77 * - ExecSeqScan() calls ExecStoreTuple() to take the result
78 * tuple from ExecProject() and place it into the result tuple slot.
80 * - ExecutePlan() calls ExecRetrieve() which gets the tuple out of
81 * the slot passed to it by calling ExecFetchTuple(). this tuple
86 * - EndPlan() calls ExecDropTupleTable() to clean up any remaining
87 * tuples left over from executing the query.
89 * The important thing to watch in the executor code is how pointers
90 * to the slots containing tuples are passed instead of the tuples
91 * themselves. This facilitates the communication of related information
92 * (such as whether or not a tuple should be pfreed, what buffer contains
93 * this tuple, the tuple's tuple descriptor, etc). Note that much of
94 * this information is also kept in the ExprContext of each node.
95 * Soon the executor will be redesigned and ExprContext's will contain
96 * only slot pointers. -cim 3/14/91
99 * The tuple table stuff is relatively new, put here to alleviate
100 * the process growth problems in the executor. The other routines
101 * are old (from the original lisp system) and may someday become
102 * obsolete. -cim 6/23/90
104 * In the implementation of nested-dot queries such as
105 * "retrieve (EMP.hobbies.all)", a single scan may return tuples
106 * of many types, so now we return pointers to tuple descriptors
107 * along with tuples returned via the tuple table. This means
108 * we now have a bunch of routines to diddle the slot descriptors
111 * The tuple table stuff depends on the executor/tuptable.h macros,
112 * and the TupleTableSlot node in execnodes.h.
116 #include "postgres.h"
117 #include "executor/executor.h"
119 #undef ExecStoreTuple
121 #include "catalog/pg_type.h"
122 #include "access/heapam.h"
124 static TupleTableSlot *NodeGetResultTupleSlot(Plan *node);
127 /* ----------------------------------------------------------------
128 * tuple table create/delete functions
129 * ----------------------------------------------------------------
131 /* --------------------------------
132 * ExecCreateTupleTable
134 * This creates a new tuple table of the specified initial
135 * size. If the size is insufficient, ExecAllocTableSlot()
136 * will grow the table as necessary.
138 * This should be used by InitPlan() to allocate the table.
139 * The table's address will be stored in the EState structure.
140 * --------------------------------
142 TupleTable /* return: address of table */
143 ExecCreateTupleTable(int initialSize) /* initial number of slots in
146 TupleTable newtable; /* newly allocated table */
147 TupleTableSlot *array; /* newly allocated slot array */
153 Assert(initialSize >= 1);
156 * Now allocate our new table along with space for the pointers
160 newtable = (TupleTable) palloc(sizeof(TupleTableData));
161 array = (TupleTableSlot *) palloc(initialSize * sizeof(TupleTableSlot));
164 * clean out the slots we just allocated
167 MemSet(array, 0, initialSize * sizeof(TupleTableSlot));
170 * initialize the new table and return it to the caller.
173 newtable->size = initialSize;
175 newtable->array = array;
180 /* --------------------------------
183 * This frees the storage used by the tuple table itself
184 * and optionally frees the contents of the table also.
185 * It is expected that this routine be called by EndPlan().
186 * --------------------------------
189 ExecDropTupleTable(TupleTable table, /* tuple table */
190 bool shouldFree) /* true if we should free slot
193 int next; /* next available slot */
194 TupleTableSlot *array; /* start of table array */
201 Assert(table != NULL);
204 * get information from the table
207 array = table->array;
211 * first free all the valid pointers in the tuple array
212 * and drop refcounts of any referenced buffers,
213 * if that's what the caller wants. (There is probably
214 * no good reason for the caller ever not to want it!)
216 * Note: we do nothing about the 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
220 * Right now, the handling of tuple pointers and buffer refcounts
221 * is clean, but the handling of tuple descriptors is NOT; they
222 * are copied around with wild abandon. It would take some work
223 * to make tuple descs pfree'able. Fortunately, since they're
224 * normally only made once per scan, it's probably not worth
225 * worrying about... tgl 9/21/99
230 for (i = 0; i < next; i++)
231 ExecClearTuple(&array[i]);
235 * finally free the tuple array and the table itself.
243 /* ----------------------------------------------------------------
244 * tuple table slot reservation functions
245 * ----------------------------------------------------------------
247 /* --------------------------------
250 * This routine is used to reserve slots in the table for
251 * use by the various plan nodes. It is expected to be
252 * called by the node init routines (ex: ExecInitNestLoop)
253 * once per slot needed by the node. Not all nodes need
254 * slots (some just pass tuples around).
255 * --------------------------------
258 ExecAllocTableSlot(TupleTable table)
260 int slotnum; /* new slot number */
261 TupleTableSlot *slot;
267 Assert(table != NULL);
270 * if our table is full we have to allocate a larger
271 * size table. Since ExecAllocTableSlot() is only called
272 * before the table is ever used to store tuples, we don't
273 * have to worry about the contents of the old table.
274 * If this changes, then we will have to preserve the contents.
277 * Unfortunately, we *cannot* do this. All of the nodes in
278 * the plan that have already initialized their slots will have
279 * pointers into _freed_ memory. This leads to bad ends. We
280 * now count the number of slots we will need and create all the
281 * slots we will need ahead of time. The if below should never
282 * happen now. Fail if it does. -mer 4 Aug 1992
285 if (table->next >= table->size)
286 elog(ERROR, "Plan requires more slots than are available"
287 "\n\tsend mail to your local executor guru to fix this");
290 * at this point, space in the table is guaranteed so we
291 * reserve the next slot, initialize and return it.
294 slotnum = table->next;
297 slot = &(table->array[slotnum]);
299 /* Make sure the allocated slot is valid (and empty) */
300 slot->type = T_TupleTableSlot;
301 slot->val = (HeapTuple) NULL;
302 slot->ttc_shouldFree = true;
303 slot->ttc_descIsNew = true;
304 slot->ttc_tupleDescriptor = (TupleDesc) NULL;
305 slot->ttc_buffer = InvalidBuffer;
306 slot->ttc_whichplan = -1;
311 /* ----------------------------------------------------------------
312 * tuple table slot accessor functions
313 * ----------------------------------------------------------------
316 /* --------------------------------
319 * This function is used to store a tuple into a specified
320 * slot in the tuple table.
322 * tuple: tuple to store
323 * slot: slot to store it in
324 * buffer: disk buffer if tuple is in a disk page, else InvalidBuffer
325 * shouldFree: true if ExecClearTuple should pfree() the tuple
328 * If 'buffer' is not InvalidBuffer, the tuple table code acquires a pin
329 * on the buffer which is held until the slot is cleared, so that the tuple
330 * won't go away on us.
332 * shouldFree is normally set 'true' for tuples constructed on-the-fly.
333 * It must always be 'false' for tuples that are stored in disk pages,
334 * since we don't want to try to pfree those.
336 * Another case where it is 'false' is when the referenced tuple is held
337 * in a tuple table slot belonging to a lower-level executor Proc node.
338 * In this case the lower-level slot retains ownership and responsibility
339 * for eventually releasing the tuple. When this method is used, we must
340 * be certain that the upper-level Proc node will lose interest in the tuple
341 * sooner than the lower-level one does! If you're not certain, copy the
342 * lower-level tuple with heap_copytuple and let the upper-level table
343 * slot assume ownership of the copy!
345 * Return value is just the passed-in slot pointer.
346 * --------------------------------
349 ExecStoreTuple(HeapTuple tuple,
350 TupleTableSlot *slot,
358 Assert(slot != NULL);
359 /* passing shouldFree=true for a tuple on a disk page is not sane */
360 Assert(BufferIsValid(buffer) ? (!shouldFree) : true);
362 /* clear out any old contents of the slot */
363 ExecClearTuple(slot);
366 * store the new tuple into the specified slot and
367 * return the slot into which we stored the tuple.
371 slot->ttc_buffer = buffer;
372 slot->ttc_shouldFree = shouldFree;
375 * If tuple is on a disk page, keep the page pinned as long as we hold
378 if (BufferIsValid(buffer))
379 IncrBufferRefCount(buffer);
384 /* --------------------------------
387 * This function is used to clear out a slot in the tuple table.
388 * --------------------------------
390 TupleTableSlot * /* return: slot passed */
391 ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
393 HeapTuple oldtuple; /* prior contents of slot */
399 Assert(slot != NULL);
402 * get information from the tuple table
405 oldtuple = slot->val;
408 * free the old contents of the specified slot if necessary.
411 if (slot->ttc_shouldFree && oldtuple != NULL)
412 heap_freetuple(oldtuple);
414 slot->val = (HeapTuple) NULL;
416 slot->ttc_shouldFree = true; /* probably useless code... */
419 * Drop the pin on the referenced buffer, if there is one.
422 if (BufferIsValid(slot->ttc_buffer))
423 ReleaseBuffer(slot->ttc_buffer);
425 slot->ttc_buffer = InvalidBuffer;
431 /* --------------------------------
434 * This function is used to get the call/don't call pfree
435 * setting of a slot. Most executor routines don't need this.
436 * It's only when you do tricky things like marking tuples for
437 * merge joins that you need to diddle the slot policy.
438 * --------------------------------
441 bool /* return: slot policy */
442 ExecSlotPolicy(TupleTableSlot *slot) /* slot to inspect */
444 return slot->ttc_shouldFree;
448 /* --------------------------------
451 * This function is used to change the call/don't call pfree
452 * setting of a slot. Most executor routines don't need this.
453 * It's only when you do tricky things like marking tuples for
454 * merge joins that you need to diddle the slot policy.
455 * --------------------------------
457 bool /* return: old slot policy */
458 ExecSetSlotPolicy(TupleTableSlot *slot, /* slot to change */
459 bool shouldFree) /* true if we call pfree() when we
462 bool old_shouldFree = slot->ttc_shouldFree;
464 slot->ttc_shouldFree = shouldFree;
466 return old_shouldFree;
471 /* --------------------------------
474 * This function is used to get the tuple descriptor associated
475 * with the slot's tuple.
477 * Now a macro in tuptable.h -mer 5 March 1992
478 * --------------------------------
481 /* --------------------------------
482 * ExecSetSlotDescriptor
484 * This function is used to set the tuple descriptor associated
485 * with the slot's tuple.
486 * --------------------------------
488 TupleDesc /* return: old slot tuple descriptor */
489 ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
490 TupleDesc tupdesc) /* tuple descriptor */
492 TupleDesc old_tupdesc = slot->ttc_tupleDescriptor;
494 slot->ttc_tupleDescriptor = tupdesc;
498 /* --------------------------------
499 * ExecSetSlotDescriptorIsNew
501 * This function is used to change the setting of the "isNew" flag
502 * --------------------------------
505 ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, /* slot to change */
506 bool isNew) /* "isNew" setting */
508 slot->ttc_descIsNew = isNew;
511 /* --------------------------------
512 * ExecSetNewSlotDescriptor
514 * This function is used to set the tuple descriptor associated
515 * with the slot's tuple, and set the "isNew" flag at the same time.
516 * --------------------------------
519 TupleDesc /* return: old slot tuple descriptor */
520 ExecSetNewSlotDescriptor(TupleTableSlot *slot, /* slot to change */
521 TupleDesc tupdesc) /* tuple descriptor */
523 TupleDesc old_tupdesc = slot->ttc_tupleDescriptor;
525 slot->ttc_tupleDescriptor = tupdesc;
526 slot->ttc_descIsNew = true;
533 /* ----------------------------------------------------------------
534 * tuple table slot status predicates
535 * ----------------------------------------------------------------
538 /* --------------------------------
539 * ExecSlotDescriptorIsNew
541 * This function is used to check if the tuple descriptor
542 * associated with this slot has just changed. ie: we are
543 * now storing a new type of tuple in this slot
544 * --------------------------------
547 bool /* return: descriptor "is new" */
548 ExecSlotDescriptorIsNew(TupleTableSlot *slot) /* slot to inspect */
550 /* bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot*) slot);
552 return slot->ttc_descIsNew;
557 /* ----------------------------------------------------------------
558 * convenience initialization routines
559 * ----------------------------------------------------------------
561 /* --------------------------------
562 * ExecInit{Result,Scan,Extra}TupleSlot
564 * These are convenience routines to initialize the specified slot
565 * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
566 * is used for initializing special-purpose slots.
567 * --------------------------------
569 #define INIT_SLOT_DEFS \
570 TupleTable tupleTable; \
573 #define INIT_SLOT_ALLOC \
574 tupleTable = (TupleTable) estate->es_tupleTable; \
575 slot = ExecAllocTableSlot(tupleTable);
578 * ExecInitResultTupleSlot
582 ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
586 commonstate->cs_ResultTupleSlot = slot;
590 * ExecInitScanTupleSlot
594 ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate)
598 commonscanstate->css_ScanTupleSlot = slot;
602 * ExecInitExtraTupleSlot
606 ExecInitExtraTupleSlot(EState *estate)
614 * ExecInitNullTupleSlot
616 * Build a slot containing an all-nulls tuple of the given type.
617 * This is used as a substitute for an input tuple when performing an
622 ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
624 TupleTableSlot* slot = ExecInitExtraTupleSlot(estate);
626 * Since heap_getattr() will treat attributes beyond a tuple's t_natts
627 * as being NULL, we can make an all-nulls tuple just by making it be of
628 * zero length. However, the slot descriptor must match the real tupType.
633 static struct tupleDesc NullTupleDesc; /* we assume this inits to
636 ExecSetSlotDescriptor(slot, tupType);
638 nullTuple = heap_formtuple(&NullTupleDesc, values, nulls);
640 return ExecStoreTuple(nullTuple, slot, InvalidBuffer, true);
644 static TupleTableSlot *
645 NodeGetResultTupleSlot(Plan *node)
647 TupleTableSlot *slot;
649 switch (nodeTag(node))
654 ResultState *resstate = ((Result *) node)->resstate;
656 slot = resstate->cstate.cs_ResultTupleSlot;
662 CommonScanState *scanstate = ((SeqScan *) node)->scanstate;
664 slot = scanstate->cstate.cs_ResultTupleSlot;
670 NestLoopState *nlstate = ((NestLoop *) node)->nlstate;
672 slot = nlstate->jstate.cs_ResultTupleSlot;
678 Append *n = (Append *) node;
679 AppendState *appendstate;
684 appendstate = n->appendstate;
685 appendplans = n->appendplans;
686 whichplan = appendstate->as_whichplan;
688 subplan = (Plan *) nth(whichplan, appendplans);
689 slot = NodeGetResultTupleSlot(subplan);
695 CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;
697 slot = scanstate->cstate.cs_ResultTupleSlot;
703 MaterialState *matstate = ((Material *) node)->matstate;
705 slot = matstate->csstate.css_ScanTupleSlot;
711 SortState *sortstate = ((Sort *) node)->sortstate;
713 slot = sortstate->csstate.css_ScanTupleSlot;
719 AggState *aggstate = ((Agg *) node)->aggstate;
721 slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
727 GroupState *grpstate = ((Group *) node)->grpstate;
729 slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
735 HashState *hashstate = ((Hash *) node)->hashstate;
737 slot = hashstate->cstate.cs_ResultTupleSlot;
743 UniqueState *uniquestate = ((Unique *) node)->uniquestate;
745 slot = uniquestate->cstate.cs_ResultTupleSlot;
751 MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate;
753 slot = mergestate->jstate.cs_ResultTupleSlot;
759 HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate;
761 slot = hashjoinstate->jstate.cs_ResultTupleSlot;
767 CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;
769 slot = scanstate->cstate.cs_ResultTupleSlot;
775 * should never get here
778 elog(ERROR, "NodeGetResultTupleSlot: node not yet supported: %d ",
786 /* ----------------------------------------------------------------
789 * this gives you the tuple descriptor for tuples returned
790 * by this node. I really wish I could ditch this routine,
791 * but since not all nodes store their type info in the same
792 * place, we have to do something special for each node type.
794 * Soon, the system will have to adapt to deal with changing
795 * tuple descriptors as we deal with dynamic tuple types
796 * being returned from procedure nodes. Perhaps then this
797 * routine can be retired. -cim 6/3/91
800 * This routine just gets the type information out of the
801 * node's state. If you already have a node's state, you
802 * can get this information directly, but this is a useful
803 * routine if you want to get the type information from
804 * the node's inner or outer subplan easily without having
805 * to inspect the subplan.. -cim 10/16/89
807 * ----------------------------------------------------------------
811 ExecGetTupType(Plan *node)
813 TupleTableSlot *slot;
819 slot = NodeGetResultTupleSlot(node);
820 tupType = slot->ttc_tupleDescriptor;
826 ExecCopyTupType(TupleDesc td, int natts)
831 newTd = CreateTemplateTupleDesc(natts);
835 newTd[i] = (Form_pg_attribute)palloc(sizeof(FormData_pg_attribute));
836 memmove(newTd[i], td[i], sizeof(FormData_pg_attribute));
843 /* ----------------------------------------------------------------
846 * Currently there are about 4 different places where we create
847 * TupleDescriptors. They should all be merged, or perhaps
848 * be rewritten to call BuildDesc().
851 * Forms attribute type info from the target list in the node.
852 * It assumes all domains are individually specified in the target list.
853 * It fails if the target list contains something like Emp.all
854 * which represents all the attributes from EMP relation.
857 * The inner and outer subtrees should be initialized because it
858 * might be necessary to know the type infos of the subtrees.
859 * ----------------------------------------------------------------
862 ExecTypeFromTL(List *targetList)
871 * examine targetlist - if empty then return NULL
874 len = ExecTargetListLength(targetList);
880 * allocate a new typeInfo
883 typeInfo = CreateTemplateTupleDesc(len);
886 * notes: get resdom from (resdom expr)
887 * get_typbyval comes from src/lib/l-lisp/lsyscache.c
893 TargetEntry *tle = lfirst(tlcdr);
895 if (tle->resdom != NULL)
897 resdom = tle->resdom;
898 restype = resdom->restype;
900 TupleDescInitEntry(typeInfo,
903 /* fix for SELECT NULL ... */
904 (restype ? restype : UNKNOWNOID),
910 ExecSetTypeInfo(resdom->resno - 1,
915 NameStr(*resdom->resname),
916 get_typbyval(restype),
917 get_typalign(restype));
924 List *fjList = lfirst(tlcdr);
928 Fjoin *fjNode = ((TargetEntry *) lfirst(fjList))->fjoin;
930 tle = fjNode->fj_innerNode; /* ??? */
933 restype = fjRes->restype;
935 TupleDescInitEntry(typeInfo,
943 ExecSetTypeInfo(fjRes->resno - 1,
948 (char *) fjRes->resname,
949 get_typbyval(restype),
950 get_typalign(restype));
953 foreach(fjTlistP, lnext(fjList))
955 TargetEntry *fjTle = lfirst(fjTlistP);
957 fjRes = fjTle->resdom;
959 TupleDescInitEntry(typeInfo,
968 ExecSetTypeInfo(fjRes->resno - 1,
970 (Oid) fjRes->restype,
973 (char *) fjRes->resname,
974 get_typbyval(fjRes->restype),
975 get_typalign(fjRes->restype));
980 tlcdr = lnext(tlcdr);