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 * Copyright (c) 1994, Regents of the University of California
17 * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.3 1996/11/08 05:56:01 momjian Exp $
19 *-------------------------------------------------------------------------
25 * ExecCreateTupleTable - create a new tuple table
26 * ExecDestroyTupleTable - destroy a table
29 * ExecAllocTableSlot - find an available slot in the table
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
45 * SLOT STATUS PREDICATES
46 * TupIsNull - true when slot contains no tuple
47 * ExecSlotDescriptorIsNew - true if we're now storing a different
48 * type of tuple in a slot
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 /
58 * ExecGetTupType - get type of tuple returned by this node
59 * ExecTypeFromTL - form a TupleDesc from a target list
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.
67 * - InitPlan() calls ExecCreateTupleTable() to create the tuple
68 * table which will hold tuples processed by the executor.
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.
77 * - SeqNext() calls ExecStoreTuple() to place the tuple returned
78 * by the access methods into the scan tuple slot.
80 * - ExecSeqScan() calls ExecStoreTuple() to take the result
81 * tuple from ExecTargetList() and place it into the result tuple
84 * - ExecutePlan() calls ExecRetrieve() which gets the tuple out of
85 * the slot passed to it by calling ExecFetchTuple(). this tuple
90 * - EndPlan() calls ExecDestroyTupleTable() to clean up any remaining
91 * tuples left over from executing the query.
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
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
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
115 * The tuple table stuff depends on the executor/tuptable.h macros,
116 * and the TupleTableSlot node in execnodes.h.
121 #include "postgres.h"
124 #include "executor/executor.h"
125 #undef ExecStoreTuple
127 #include "access/tupdesc.h"
128 #include "utils/palloc.h"
129 #include "utils/lsyscache.h"
130 #include "storage/bufmgr.h"
131 #include "parser/catalog_utils.h"
133 /* ----------------------------------------------------------------
134 * tuple table create/delete functions
135 * ----------------------------------------------------------------
137 /* --------------------------------
138 * ExecCreateTupleTable
140 * This creates a new tuple table of the specified initial
141 * size. If the size is insufficient, ExecAllocTableSlot()
142 * will grow the table as necessary.
144 * This should be used by InitPlan() to allocate the table.
145 * The table's address will be stored in the EState structure.
146 * --------------------------------
148 TupleTable /* return: address of table */
149 ExecCreateTupleTable(int initialSize) /* initial number of slots in table */
151 TupleTable newtable; /* newly allocated table */
152 TupleTableSlot* array; /* newly allocated slot array */
158 Assert(initialSize >= 1);
161 * Now allocate our new table along with space for the pointers
165 newtable = (TupleTable) palloc(sizeof(TupleTableData));
166 array = (TupleTableSlot*) palloc(initialSize * sizeof(TupleTableSlot));
169 * clean out the slots we just allocated
172 memset(array, 0, initialSize * sizeof(TupleTableSlot));
175 * initialize the new table and return it to the caller.
178 newtable->size = initialSize;
180 newtable->array = array;
185 /* --------------------------------
186 * ExecDestroyTupleTable
188 * This pfrees the storage assigned to the tuple table and
189 * optionally pfrees the contents of the table also.
190 * It is expected that this routine be called by EndPlan().
191 * --------------------------------
194 ExecDestroyTupleTable(TupleTable table, /* tuple table */
195 bool shouldFree) /* true if we should free slot contents */
197 int next; /* next avaliable slot */
198 TupleTableSlot *array; /* start of table array */
205 Assert(table != NULL);
208 * get information from the table
211 array = table->array;
215 * first free all the valid pointers in the tuple array
216 * if that's what the caller wants..
218 * Note: we do nothing about the Buffer and Tuple Descriptor's
219 * we store in the slots. This may have to change (ex: we should
220 * probably worry about pfreeing tuple descs too) -cim 3/14/91
224 for (i = 0; i < next; i++) {
232 slot.val = (HeapTuple)NULL;
233 if (slot.ttc_shouldFree) {
235 * since a tuple may contain a pointer to
236 * lock information allocated along with the
237 * tuple, we have to be careful to free any
238 * rule locks also -cim 1/17/90
247 * finally free the tuple array and the table itself.
256 /* ----------------------------------------------------------------
257 * tuple table slot reservation functions
258 * ----------------------------------------------------------------
260 /* --------------------------------
263 * This routine is used to reserve slots in the table for
264 * use by the various plan nodes. It is expected to be
265 * called by the node init routines (ex: ExecInitNestLoop).
266 * once per slot needed by the node. Not all nodes need
267 * slots (some just pass tuples around).
268 * --------------------------------
270 TupleTableSlot* /* return: the slot allocated in the tuple table */
271 ExecAllocTableSlot(TupleTable table)
273 int slotnum; /* new slot number */
279 Assert(table != NULL);
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.
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
297 if (table->next >= table->size) {
299 * int newsize = NewTableSize(table->size);
301 * pfree(table->array);
302 * table->array = (Pointer) palloc(newsize * TableSlotSize);
303 * bzero(table->array, newsize * TableSlotSize);
304 * table->size = newsize;
306 elog(NOTICE, "Plan requires more slots than are available");
307 elog(WARN, "send mail to your local executor guru to fix this");
311 * at this point, space in the table is guaranteed so we
312 * reserve the next slot, initialize and return it.
315 slotnum = table->next;
318 table->array[slotnum].type = T_TupleTableSlot;
320 return &(table->array[slotnum]);
323 /* ----------------------------------------------------------------
324 * tuple table slot accessor functions
325 * ----------------------------------------------------------------
328 /* --------------------------------
331 * This function is used to store a tuple into a specified
332 * slot in the tuple table. Note: the only slots which should
333 * be called with shouldFree == false are those slots used to
334 * store tuples not allocated with pfree(). Currently the
335 * seqscan and indexscan nodes use this for the tuples returned
336 * by amgetattr, which are actually pointers onto disk pages.
337 * --------------------------------
339 TupleTableSlot* /* return: slot passed */
340 ExecStoreTuple(HeapTuple tuple, /* tuple to store */
341 TupleTableSlot* slot, /* slot in which to store tuple */
342 Buffer buffer, /* buffer associated with tuple */
343 bool shouldFree) /* true if we call pfree() when we gc. */
349 Assert(slot != NULL);
351 /* clear out the slot first */
352 ExecClearTuple(slot);
355 * store the new tuple into the specified slot and
356 * return the slot into which we stored the tuple.
360 slot->ttc_buffer = buffer;
361 slot->ttc_shouldFree = shouldFree;
366 /* --------------------------------
369 * This function is used to clear out a slot in the tuple table.
370 * --------------------------------
372 TupleTableSlot* /* return: slot passed */
373 ExecClearTuple(TupleTableSlot* slot) /* slot in which to store tuple */
375 HeapTuple oldtuple; /* prior contents of slot */
381 Assert(slot != NULL);
384 * get information from the tuple table
387 oldtuple = slot->val;
390 * free the old contents of the specified slot if necessary.
393 if (slot->ttc_shouldFree && oldtuple != NULL) {
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
405 * store NULL into the specified slot and return the slot.
406 * - also set buffer to InvalidBuffer -cim 3/14/91
409 slot->val = (HeapTuple)NULL;
411 if (BufferIsValid(slot->ttc_buffer))
412 ReleaseBuffer(slot->ttc_buffer);
414 slot->ttc_buffer = InvalidBuffer;
415 slot->ttc_shouldFree = true;
421 /* --------------------------------
424 * This function is used to get the call/don't call pfree
425 * setting of a slot. Most executor routines don't need this.
426 * It's only when you do tricky things like marking tuples for
427 * merge joins that you need to diddle the slot policy.
428 * --------------------------------
430 bool /* return: slot policy */
431 ExecSlotPolicy(TupleTableSlot* slot) /* slot to inspect */
433 return slot->ttc_shouldFree;
436 /* --------------------------------
439 * This function is used to change the call/don't call pfree
440 * setting of a slot. Most executor routines don't need this.
441 * It's only when you do tricky things like marking tuples for
442 * merge joins that you need to diddle the slot policy.
443 * --------------------------------
445 bool /* return: old slot policy */
446 ExecSetSlotPolicy(TupleTableSlot* slot, /* slot to change */
447 bool shouldFree) /* true if we call pfree() when we gc. */
449 bool old_shouldFree = slot->ttc_shouldFree;
450 slot->ttc_shouldFree = shouldFree;
452 return old_shouldFree;
455 /* --------------------------------
458 * This function is used to get the tuple descriptor associated
459 * with the slot's tuple.
461 * Now a macro in tuptable.h -mer 5 March 1992
462 * --------------------------------
465 /* --------------------------------
466 * ExecSetSlotDescriptor
468 * This function is used to set the tuple descriptor associated
469 * with the slot's tuple.
470 * --------------------------------
472 TupleDesc /* return: old slot tuple descriptor */
473 ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
474 TupleDesc tupdesc) /* tuple descriptor */
476 TupleDesc old_tupdesc = slot->ttc_tupleDescriptor;
478 slot->ttc_tupleDescriptor = tupdesc;
482 /* --------------------------------
483 * ExecSetSlotDescriptorIsNew
485 * This function is used to change the setting of the "isNew" flag
486 * --------------------------------
489 ExecSetSlotDescriptorIsNew(TupleTableSlot *slot,/* slot to change */
490 bool isNew) /* "isNew" setting */
492 slot->ttc_descIsNew = isNew;
495 /* --------------------------------
496 * ExecSetNewSlotDescriptor
498 * This function is used to set the tuple descriptor associated
499 * with the slot's tuple, and set the "isNew" flag at the same time.
500 * --------------------------------
502 TupleDesc /* return: old slot tuple descriptor */
503 ExecSetNewSlotDescriptor(TupleTableSlot *slot, /* slot to change */
504 TupleDesc tupdesc) /* tuple descriptor */
506 TupleDesc old_tupdesc = slot->ttc_tupleDescriptor;
507 slot->ttc_tupleDescriptor = tupdesc;
508 slot->ttc_descIsNew = true;
513 /* --------------------------------
516 * This function is used to get the tuple descriptor associated
517 * with the slot's tuple. Be very careful with this as it does not
518 * balance the reference counts. If the buffer returned is stored
519 * someplace else, then also use ExecIncrSlotBufferRefcnt().
521 * Now a macro in tuptable.h
522 * --------------------------------
525 /* --------------------------------
528 * This function is used to set the tuple descriptor associated
529 * with the slot's tuple. Be very careful with this as it does not
530 * balance the reference counts. If we're using this then we should
531 * also use ExecIncrSlotBufferRefcnt().
532 * --------------------------------
534 Buffer /* return: old slot buffer */
535 ExecSetSlotBuffer(TupleTableSlot *slot, /* slot to change */
536 Buffer b) /* tuple descriptor */
538 Buffer oldb = slot->ttc_buffer;
539 slot->ttc_buffer = b;
544 /* --------------------------------
545 * ExecIncrSlotBufferRefcnt
547 * When we pass around buffers in the tuple table, we have to
548 * be careful to increment reference counts appropriately.
549 * This is used mainly in the mergejoin code.
550 * --------------------------------
553 ExecIncrSlotBufferRefcnt(TupleTableSlot *slot) /* slot to bump refcnt */
555 /* Buffer b = SlotBuffer((TupleTableSlot*) slot); */
556 Buffer b = slot->ttc_buffer;
557 if (BufferIsValid(b))
558 IncrBufferRefCount(b);
561 /* ----------------------------------------------------------------
562 * tuple table slot status predicates
563 * ----------------------------------------------------------------
569 * This is used mainly to detect when there are no more
573 bool /* return: true if tuple in slot is NULL */
574 TupIsNull(TupleTableSlot* slot) /* slot to check */
576 HeapTuple tuple; /* contents of slot (returned) */
579 * if the slot itself is null then we return true
586 * get information from the slot and return true or
587 * false depending on the contents of the slot.
593 (tuple == NULL ? true : false);
596 /* --------------------------------
597 * ExecSlotDescriptorIsNew
599 * This function is used to check if the tuple descriptor
600 * associated with this slot has just changed. ie: we are
601 * now storing a new type of tuple in this slot
602 * --------------------------------
604 bool /* return: descriptor "is new" */
605 ExecSlotDescriptorIsNew(TupleTableSlot *slot) /* slot to inspect */
607 /* bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot*) slot);
609 return slot->ttc_descIsNew;
612 /* ----------------------------------------------------------------
613 * convenience initialization routines
614 * ----------------------------------------------------------------
616 /* --------------------------------
617 * ExecInit{Result,Scan,Raw,Marked,Outer,Hash}TupleSlot
619 * These are convenience routines to initialize the specfied slot
620 * in nodes inheriting the appropriate state.
621 * --------------------------------
623 #define INIT_SLOT_DEFS \
624 TupleTable tupleTable; \
627 #define INIT_SLOT_ALLOC \
628 tupleTable = (TupleTable) estate->es_tupleTable; \
629 slot = ExecAllocTableSlot(tupleTable); \
630 slot->val = (HeapTuple)NULL; \
631 slot->ttc_shouldFree = true; \
632 slot->ttc_tupleDescriptor = (TupleDesc)NULL; \
633 slot->ttc_whichplan = -1;\
634 slot->ttc_descIsNew = true;
637 * ExecInitResultTupleSlot
641 ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
645 commonstate->cs_ResultTupleSlot = (TupleTableSlot *) slot;
649 * ExecInitScanTupleSlot
653 ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate)
657 commonscanstate->css_ScanTupleSlot = (TupleTableSlot *)slot;
661 * ExecInitMarkedTupleSlot
665 ExecInitMarkedTupleSlot(EState *estate, MergeJoinState *mergestate)
669 mergestate->mj_MarkedTupleSlot = (TupleTableSlot *) slot;
673 * ExecInitOuterTupleSlot
677 ExecInitOuterTupleSlot(EState *estate, HashJoinState *hashstate)
681 hashstate->hj_OuterTupleSlot = slot;
685 * ExecInitHashTupleSlot
689 ExecInitHashTupleSlot(EState *estate, HashJoinState *hashstate)
693 hashstate->hj_HashTupleSlot = slot;
697 NodeGetResultTupleSlot(Plan *node)
699 TupleTableSlot *slot;
701 switch(nodeTag(node)) {
705 ResultState *resstate = ((Result *)node)->resstate;
706 slot = resstate->cstate.cs_ResultTupleSlot;
712 CommonScanState *scanstate = ((SeqScan *)node)->scanstate;
713 slot = scanstate->cstate.cs_ResultTupleSlot;
719 NestLoopState *nlstate = ((NestLoop *)node)->nlstate;
720 slot = nlstate->jstate.cs_ResultTupleSlot;
726 Append *n = (Append *)node;
727 AppendState *unionstate;
732 unionstate = n->unionstate;
733 unionplans = n->unionplans;
734 whichplan = unionstate->as_whichplan;
736 subplan = (Plan*) nth(whichplan, unionplans);
737 slot = NodeGetResultTupleSlot(subplan);
743 CommonScanState *scanstate = ((IndexScan *)node)->scan.scanstate;
744 slot = scanstate->cstate.cs_ResultTupleSlot;
750 MaterialState *matstate = ((Material *)node)->matstate;
751 slot = matstate->csstate.css_ScanTupleSlot;
757 SortState *sortstate = ((Sort *)node)->sortstate;
758 slot = sortstate->csstate.css_ScanTupleSlot;
764 AggState *aggstate = ((Agg *)node)->aggstate;
765 slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
771 GroupState *grpstate = ((Group *)node)->grpstate;
772 slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
778 HashState *hashstate = ((Hash *)node)->hashstate;
779 slot = hashstate->cstate.cs_ResultTupleSlot;
785 UniqueState *uniquestate = ((Unique *)node)->uniquestate;
786 slot = uniquestate->cs_ResultTupleSlot;
792 MergeJoinState *mergestate = ((MergeJoin *)node)->mergestate;
793 slot = mergestate->jstate.cs_ResultTupleSlot;
799 HashJoinState *hashjoinstate = ((HashJoin *)node)->hashjoinstate;
800 slot = hashjoinstate->jstate.cs_ResultTupleSlot;
806 TeeState *teestate = ((Tee*)node)->teestate;
807 slot = teestate->cstate.cs_ResultTupleSlot;
813 * should never get here
816 elog(WARN, "NodeGetResultTupleSlot: node not yet supported: %d ",
824 /* ----------------------------------------------------------------
827 * this gives you the tuple descriptor for tuples returned
828 * by this node. I really wish I could ditch this routine,
829 * but since not all nodes store their type info in the same
830 * place, we have to do something special for each node type.
832 * Soon, the system will have to adapt to deal with changing
833 * tuple descriptors as we deal with dynamic tuple types
834 * being returned from procedure nodes. Perhaps then this
835 * routine can be retired. -cim 6/3/91
838 * This routine just gets the type information out of the
839 * node's state. If you already have a node's state, you
840 * can get this information directly, but this is a useful
841 * routine if you want to get the type information from
842 * the node's inner or outer subplan easily without having
843 * to inspect the subplan.. -cim 10/16/89
845 * Assume that for existential nodes, we get the targetlist out
846 * of the right node's targetlist
847 * ----------------------------------------------------------------
851 ExecGetTupType(Plan *node)
853 TupleTableSlot *slot;
859 slot = NodeGetResultTupleSlot(node);
860 tupType = slot->ttc_tupleDescriptor;
866 ExecCopyTupType(TupleDesc td, int natts)
871 newTd = CreateTemplateTupleDesc(natts);
876 (AttributeTupleForm)palloc(sizeof(FormData_pg_attribute));
877 memmove(newTd[i], td[i], sizeof(FormData_pg_attribute));
884 /* ----------------------------------------------------------------
887 * Currently there are about 4 different places where we create
888 * TupleDescriptors. They should all be merged, or perhaps
889 * be rewritten to call BuildDesc().
892 * Forms attribute type info from the target list in the node.
893 * It assumes all domains are individually specified in the target list.
894 * It fails if the target list contains something like Emp.all
895 * which represents all the attributes from EMP relation.
898 * The inner and outer subtrees should be initialized because it
899 * might be necessary to know the type infos of the subtrees.
900 * ----------------------------------------------------------------
903 ExecTypeFromTL(List *targetList)
912 * examine targetlist - if empty then return NULL
915 len = ExecTargetListLength(targetList);
921 * allocate a new typeInfo
924 typeInfo = CreateTemplateTupleDesc(len);
927 * notes: get resdom from (resdom expr)
928 * get_typbyval comes from src/lib/l-lisp/lsyscache.c
932 while (tlcdr != NIL) {
933 TargetEntry *tle = lfirst(tlcdr);
934 if (tle->resdom != NULL) {
935 resdom = tle->resdom;
936 restype = resdom->restype;
938 TupleDescInitEntry(typeInfo,
941 get_id_typname(restype),
946 ExecSetTypeInfo(resdom->resno - 1,
951 resdom->resname->data,
952 get_typbyval(restype),
953 get_typalign(restype));
959 List *fjList = lfirst(tlcdr);
962 Fjoin *fjNode = ((TargetEntry *)lfirst(fjList))->fjoin;
964 tle = fjNode->fj_innerNode; /* ??? */
967 restype = fjRes->restype;
969 TupleDescInitEntry(typeInfo,
972 get_id_typname(restype),
976 ExecSetTypeInfo(fjRes->resno - 1,
981 (char *) fjRes->resname,
982 get_typbyval(restype),
983 get_typalign(restype));
986 foreach(fjTlistP, lnext(fjList)) {
987 TargetEntry *fjTle = lfirst(fjTlistP);
989 fjRes = fjTle->resdom;
991 TupleDescInitEntry(typeInfo,
994 get_id_typname(restype),
999 ExecSetTypeInfo(fjRes->resno - 1,
1001 (Oid) fjRes->restype,
1004 (char *) fjRes->resname,
1005 get_typbyval(fjRes->restype),
1006 get_typalign(fjRes->restype));
1011 tlcdr = lnext(tlcdr);