diff options
Diffstat (limited to 'src/backend/executor/execTuples.c')
-rw-r--r-- | src/backend/executor/execTuples.c | 1526 |
1 files changed, 781 insertions, 745 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 0d5e7fda9fb..287f75699af 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -1,119 +1,119 @@ /*------------------------------------------------------------------------- * * execTuples.c-- - * Routines dealing with the executor tuple tables. These are used to - * ensure that the executor frees copies of tuples (made by - * ExecTargetList) properly. + * Routines dealing with the executor tuple tables. These are used to + * ensure that the executor frees copies of tuples (made by + * ExecTargetList) properly. + * + * Routines dealing with the type information for tuples. Currently, + * the type information for a tuple is an array of FormData_pg_attribute. + * This information is needed by routines manipulating tuples + * (getattribute, formtuple, etc.). * - * Routines dealing with the type information for tuples. Currently, - * the type information for a tuple is an array of FormData_pg_attribute. - * This information is needed by routines manipulating tuples - * (getattribute, formtuple, etc.). - * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.6 1997/08/19 21:31:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.7 1997/09/07 04:41:24 momjian Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES * - * TABLE CREATE/DELETE - * ExecCreateTupleTable - create a new tuple table - * ExecDestroyTupleTable - destroy a table + * TABLE CREATE/DELETE + * ExecCreateTupleTable - create a new tuple table + * ExecDestroyTupleTable - destroy a table * - * SLOT RESERVERATION - * ExecAllocTableSlot - find an available slot in the table + * SLOT RESERVERATION + * ExecAllocTableSlot - find an available slot in the table * - * SLOT ACCESSORS - * ExecStoreTuple - store a tuple in the table - * ExecFetchTuple - fetch a tuple from the table - * ExecClearTuple - clear contents of a table slot - * ExecSlotPolicy - return slot's tuple pfree policy - * ExecSetSlotPolicy - diddle the slot policy - * ExecSlotDescriptor - type of tuple in a slot - * ExecSetSlotDescriptor - set a slot's tuple descriptor - * ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag - * ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once - * ExecSlotBuffer - return buffer of tuple in slot - * ExecSetSlotBuffer - set the buffer for tuple in slot - * ExecIncrSlotBufferRefcnt - bump the refcnt of the slot buffer + * SLOT ACCESSORS + * ExecStoreTuple - store a tuple in the table + * ExecFetchTuple - fetch a tuple from the table + * ExecClearTuple - clear contents of a table slot + * ExecSlotPolicy - return slot's tuple pfree policy + * ExecSetSlotPolicy - diddle the slot policy + * ExecSlotDescriptor - type of tuple in a slot + * ExecSetSlotDescriptor - set a slot's tuple descriptor + * ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag + * ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once + * ExecSlotBuffer - return buffer of tuple in slot + * ExecSetSlotBuffer - set the buffer for tuple in slot + * ExecIncrSlotBufferRefcnt - bump the refcnt of the slot buffer * - * SLOT STATUS PREDICATES - * TupIsNull - true when slot contains no tuple - * ExecSlotDescriptorIsNew - true if we're now storing a different - * type of tuple in a slot + * SLOT STATUS PREDICATES + * TupIsNull - true when slot contains no tuple + * ExecSlotDescriptorIsNew - true if we're now storing a different + * type of tuple in a slot * - * CONVENIENCE INITIALIZATION ROUTINES - * ExecInitResultTupleSlot \ convience routines to initialize - * ExecInitScanTupleSlot \ the various tuple slots for nodes - * ExecInitMarkedTupleSlot / which store copies of tuples. - * ExecInitOuterTupleSlot / - * ExecInitHashTupleSlot / + * CONVENIENCE INITIALIZATION ROUTINES + * ExecInitResultTupleSlot \ convience routines to initialize + * ExecInitScanTupleSlot \ the various tuple slots for nodes + * ExecInitMarkedTupleSlot / which store copies of tuples. + * ExecInitOuterTupleSlot / + * ExecInitHashTupleSlot / * - * old routines: - * ExecGetTupType - get type of tuple returned by this node - * ExecTypeFromTL - form a TupleDesc from a target list + * old routines: + * ExecGetTupType - get type of tuple returned by this node + * ExecTypeFromTL - form a TupleDesc from a target list * - * EXAMPLE OF HOW TABLE ROUTINES WORK - * Suppose we have a query such as retrieve (EMP.name) and we have - * a single SeqScan node in the query plan. + * EXAMPLE OF HOW TABLE ROUTINES WORK + * Suppose we have a query such as retrieve (EMP.name) and we have + * a single SeqScan node in the query plan. * - * At ExecStart() - * ---------------- - * - InitPlan() calls ExecCreateTupleTable() to create the tuple - * table which will hold tuples processed by the executor. + * At ExecStart() + * ---------------- + * - InitPlan() calls ExecCreateTupleTable() to create the tuple + * table which will hold tuples processed by the executor. * - * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and - * ExecInitResultTupleSlot() to reserve places in the tuple - * table for the tuples returned by the access methods and the - * tuples resulting from preforming target list projections. + * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and + * ExecInitResultTupleSlot() to reserve places in the tuple + * table for the tuples returned by the access methods and the + * tuples resulting from preforming target list projections. * - * During ExecRun() - * ---------------- - * - SeqNext() calls ExecStoreTuple() to place the tuple returned - * by the access methods into the scan tuple slot. + * During ExecRun() + * ---------------- + * - SeqNext() calls ExecStoreTuple() to place the tuple returned + * by the access methods into the scan tuple slot. * - * - ExecSeqScan() calls ExecStoreTuple() to take the result - * tuple from ExecTargetList() and place it into the result tuple - * slot. + * - ExecSeqScan() calls ExecStoreTuple() to take the result + * tuple from ExecTargetList() and place it into the result tuple + * slot. * - * - ExecutePlan() calls ExecRetrieve() which gets the tuple out of - * the slot passed to it by calling ExecFetchTuple(). this tuple - * is then returned. + * - ExecutePlan() calls ExecRetrieve() which gets the tuple out of + * the slot passed to it by calling ExecFetchTuple(). this tuple + * is then returned. * - * At ExecEnd() - * ---------------- - * - EndPlan() calls ExecDestroyTupleTable() to clean up any remaining - * tuples left over from executing the query. + * At ExecEnd() + * ---------------- + * - EndPlan() calls ExecDestroyTupleTable() to clean up any remaining + * tuples left over from executing the query. * - * The important thing to watch in the executor code is how pointers - * to the slots containing tuples are passed instead of the tuples - * themselves. This facilitates the communication of related information - * (such as whether or not a tuple should be pfreed, what buffer contains - * this tuple, the tuple's tuple descriptor, etc). Note that much of - * this information is also kept in the ExprContext of each node. - * Soon the executor will be redesigned and ExprContext's will contain - * only slot pointers. -cim 3/14/91 + * The important thing to watch in the executor code is how pointers + * to the slots containing tuples are passed instead of the tuples + * themselves. This facilitates the communication of related information + * (such as whether or not a tuple should be pfreed, what buffer contains + * this tuple, the tuple's tuple descriptor, etc). Note that much of + * this information is also kept in the ExprContext of each node. + * Soon the executor will be redesigned and ExprContext's will contain + * only slot pointers. -cim 3/14/91 * - * NOTES - * The tuple table stuff is relatively new, put here to alleviate - * the process growth problems in the executor. The other routines - * are old (from the original lisp system) and may someday become - * obsolete. -cim 6/23/90 + * NOTES + * The tuple table stuff is relatively new, put here to alleviate + * the process growth problems in the executor. The other routines + * are old (from the original lisp system) and may someday become + * obsolete. -cim 6/23/90 * - * In the implementation of nested-dot queries such as - * "retrieve (EMP.hobbies.all)", a single scan may return tuples - * of many types, so now we return pointers to tuple descriptors - * along with tuples returned via the tuple table. This means - * we now have a bunch of routines to diddle the slot descriptors - * too. -cim 1/18/90 + * In the implementation of nested-dot queries such as + * "retrieve (EMP.hobbies.all)", a single scan may return tuples + * of many types, so now we return pointers to tuple descriptors + * along with tuples returned via the tuple table. This means + * we now have a bunch of routines to diddle the slot descriptors + * too. -cim 1/18/90 * - * The tuple table stuff depends on the executor/tuptable.h macros, - * and the TupleTableSlot node in execnodes.h. + * The tuple table stuff depends on the executor/tuptable.h macros, + * and the TupleTableSlot node in execnodes.h. * */ #include <string.h> @@ -131,902 +131,938 @@ #include "parser/catalog_utils.h" #include "catalog/pg_type.h" -static TupleTableSlot *NodeGetResultTupleSlot(Plan *node); +static TupleTableSlot *NodeGetResultTupleSlot(Plan * node); /* ---------------------------------------------------------------- - * tuple table create/delete functions + * tuple table create/delete functions * ---------------------------------------------------------------- */ /* -------------------------------- - * ExecCreateTupleTable + * ExecCreateTupleTable * - * This creates a new tuple table of the specified initial - * size. If the size is insufficient, ExecAllocTableSlot() - * will grow the table as necessary. + * This creates a new tuple table of the specified initial + * size. If the size is insufficient, ExecAllocTableSlot() + * will grow the table as necessary. * - * This should be used by InitPlan() to allocate the table. - * The table's address will be stored in the EState structure. + * This should be used by InitPlan() to allocate the table. + * The table's address will be stored in the EState structure. * -------------------------------- */ -TupleTable /* return: address of table */ -ExecCreateTupleTable(int initialSize) /* initial number of slots in table */ +TupleTable /* return: address of table */ +ExecCreateTupleTable(int initialSize) /* initial number of slots + * in table */ { - TupleTable newtable; /* newly allocated table */ - TupleTableSlot* array; /* newly allocated slot array */ - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(initialSize >= 1); - - /* ---------------- - * Now allocate our new table along with space for the pointers - * to the tuples. - */ - - newtable = (TupleTable) palloc(sizeof(TupleTableData)); - array = (TupleTableSlot*) palloc(initialSize * sizeof(TupleTableSlot)); - - /* ---------------- - * clean out the slots we just allocated - * ---------------- - */ - memset(array, 0, initialSize * sizeof(TupleTableSlot)); - - /* ---------------- - * initialize the new table and return it to the caller. - * ---------------- - */ - newtable->size = initialSize; - newtable->next = 0; - newtable->array = array; - - return newtable; + TupleTable newtable; /* newly allocated table */ + TupleTableSlot *array; /* newly allocated slot array */ + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(initialSize >= 1); + + /* ---------------- + * Now allocate our new table along with space for the pointers + * to the tuples. + */ + + newtable = (TupleTable) palloc(sizeof(TupleTableData)); + array = (TupleTableSlot *) palloc(initialSize * sizeof(TupleTableSlot)); + + /* ---------------- + * clean out the slots we just allocated + * ---------------- + */ + memset(array, 0, initialSize * sizeof(TupleTableSlot)); + + /* ---------------- + * initialize the new table and return it to the caller. + * ---------------- + */ + newtable->size = initialSize; + newtable->next = 0; + newtable->array = array; + + return newtable; } /* -------------------------------- - * ExecDestroyTupleTable + * ExecDestroyTupleTable * - * This pfrees the storage assigned to the tuple table and - * optionally pfrees the contents of the table also. - * It is expected that this routine be called by EndPlan(). + * This pfrees the storage assigned to the tuple table and + * optionally pfrees the contents of the table also. + * It is expected that this routine be called by EndPlan(). * -------------------------------- */ void -ExecDestroyTupleTable(TupleTable table, /* tuple table */ - bool shouldFree) /* true if we should free slot contents */ +ExecDestroyTupleTable(TupleTable table, /* tuple table */ + bool shouldFree) /* true if we should free slot + * contents */ { - int next; /* next avaliable slot */ - TupleTableSlot *array; /* start of table array */ - int i; /* counter */ - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(table != NULL); - - /* ---------------- - * get information from the table - * ---------------- - */ - array = table->array; - next = table->next; - - /* ---------------- - * first free all the valid pointers in the tuple array - * if that's what the caller wants.. - * - * Note: we do nothing about the Buffer and Tuple Descriptor's - * we store in the slots. This may have to change (ex: we should - * probably worry about pfreeing tuple descs too) -cim 3/14/91 - * ---------------- - */ - if (shouldFree) - for (i = 0; i < next; i++) { - TupleTableSlot slot; - HeapTuple tuple; - - slot = array[i]; - tuple = slot.val; - - if (tuple != NULL) { - slot.val = (HeapTuple)NULL; - if (slot.ttc_shouldFree) { - /* ---------------- - * since a tuple may contain a pointer to - * lock information allocated along with the - * tuple, we have to be careful to free any - * rule locks also -cim 1/17/90 - * ---------------- - */ - pfree(tuple); + int next; /* next avaliable slot */ + TupleTableSlot *array; /* start of table array */ + int i; /* counter */ + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(table != NULL); + + /* ---------------- + * get information from the table + * ---------------- + */ + array = table->array; + next = table->next; + + /* ---------------- + * first free all the valid pointers in the tuple array + * if that's what the caller wants.. + * + * Note: we do nothing about the Buffer and Tuple Descriptor's + * we store in the slots. This may have to change (ex: we should + * probably worry about pfreeing tuple descs too) -cim 3/14/91 + * ---------------- + */ + if (shouldFree) + for (i = 0; i < next; i++) + { + TupleTableSlot slot; + HeapTuple tuple; + + slot = array[i]; + tuple = slot.val; + + if (tuple != NULL) + { + slot.val = (HeapTuple) NULL; + if (slot.ttc_shouldFree) + { + /* ---------------- + * since a tuple may contain a pointer to + * lock information allocated along with the + * tuple, we have to be careful to free any + * rule locks also -cim 1/17/90 + * ---------------- + */ + pfree(tuple); + } + } } - } - } - - /* ---------------- - * finally free the tuple array and the table itself. - * ---------------- - */ - pfree(array); - pfree(table); - + + /* ---------------- + * finally free the tuple array and the table itself. + * ---------------- + */ + pfree(array); + pfree(table); + } /* ---------------------------------------------------------------- - * tuple table slot reservation functions + * tuple table slot reservation functions * ---------------------------------------------------------------- */ /* -------------------------------- - * ExecAllocTableSlot + * ExecAllocTableSlot * - * This routine is used to reserve slots in the table for - * use by the various plan nodes. It is expected to be - * called by the node init routines (ex: ExecInitNestLoop). - * once per slot needed by the node. Not all nodes need - * slots (some just pass tuples around). + * This routine is used to reserve slots in the table for + * use by the various plan nodes. It is expected to be + * called by the node init routines (ex: ExecInitNestLoop). + * once per slot needed by the node. Not all nodes need + * slots (some just pass tuples around). * -------------------------------- */ -TupleTableSlot* /* return: the slot allocated in the tuple table */ +TupleTableSlot * /* return: the slot allocated in the tuple + * table */ ExecAllocTableSlot(TupleTable table) { - int slotnum; /* new slot number */ - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(table != NULL); - - /* ---------------- - * if our table is full we have to allocate a larger - * size table. Since ExecAllocTableSlot() is only called - * before the table is ever used to store tuples, we don't - * have to worry about the contents of the old table. - * If this changes, then we will have to preserve the contents. - * -cim 6/23/90 - * - * Unfortunately, we *cannot* do this. All of the nodes in - * the plan that have already initialized their slots will have - * pointers into _freed_ memory. This leads to bad ends. We - * now count the number of slots we will need and create all the - * slots we will need ahead of time. The if below should never - * happen now. Give a WARN if it does. -mer 4 Aug 1992 - * ---------------- - */ - if (table->next >= table->size) { - /* - * int newsize = NewTableSize(table->size); + int slotnum; /* new slot number */ + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(table != NULL); + + /* ---------------- + * if our table is full we have to allocate a larger + * size table. Since ExecAllocTableSlot() is only called + * before the table is ever used to store tuples, we don't + * have to worry about the contents of the old table. + * If this changes, then we will have to preserve the contents. + * -cim 6/23/90 * - * pfree(table->array); - * table->array = (Pointer) palloc(newsize * TableSlotSize); - * bzero(table->array, newsize * TableSlotSize); - * table->size = newsize; + * Unfortunately, we *cannot* do this. All of the nodes in + * the plan that have already initialized their slots will have + * pointers into _freed_ memory. This leads to bad ends. We + * now count the number of slots we will need and create all the + * slots we will need ahead of time. The if below should never + * happen now. Give a WARN if it does. -mer 4 Aug 1992 + * ---------------- */ - elog(NOTICE, "Plan requires more slots than are available"); - elog(WARN, "send mail to your local executor guru to fix this"); - } - - /* ---------------- - * at this point, space in the table is guaranteed so we - * reserve the next slot, initialize and return it. - * ---------------- - */ - slotnum = table->next; - table->next++; - - table->array[slotnum].type = T_TupleTableSlot; - - return &(table->array[slotnum]); + if (table->next >= table->size) + { + + /* + * int newsize = NewTableSize(table->size); + * + * pfree(table->array); table->array = (Pointer) palloc(newsize * + * TableSlotSize); bzero(table->array, newsize * TableSlotSize); + * table->size = newsize; + */ + elog(NOTICE, "Plan requires more slots than are available"); + elog(WARN, "send mail to your local executor guru to fix this"); + } + + /* ---------------- + * at this point, space in the table is guaranteed so we + * reserve the next slot, initialize and return it. + * ---------------- + */ + slotnum = table->next; + table->next++; + + table->array[slotnum].type = T_TupleTableSlot; + + return &(table->array[slotnum]); } /* ---------------------------------------------------------------- - * tuple table slot accessor functions + * tuple table slot accessor functions * ---------------------------------------------------------------- */ /* -------------------------------- - * ExecStoreTuple + * ExecStoreTuple * - * This function is used to store a tuple into a specified - * slot in the tuple table. Note: the only slots which should - * be called with shouldFree == false are those slots used to - * store tuples not allocated with pfree(). Currently the - * seqscan and indexscan nodes use this for the tuples returned - * by amgetattr, which are actually pointers onto disk pages. + * This function is used to store a tuple into a specified + * slot in the tuple table. Note: the only slots which should + * be called with shouldFree == false are those slots used to + * store tuples not allocated with pfree(). Currently the + * seqscan and indexscan nodes use this for the tuples returned + * by amgetattr, which are actually pointers onto disk pages. * -------------------------------- */ -TupleTableSlot* /* return: slot passed */ -ExecStoreTuple(HeapTuple tuple, /* tuple to store */ - TupleTableSlot* slot, /* slot in which to store tuple */ - Buffer buffer, /* buffer associated with tuple */ - bool shouldFree) /* true if we call pfree() when we gc. */ +TupleTableSlot * /* return: slot passed */ +ExecStoreTuple(HeapTuple tuple, /* tuple to store */ + TupleTableSlot * slot, /* slot in which to store tuple */ + Buffer buffer, /* buffer associated with tuple */ + bool shouldFree) /* true if we call pfree() when we gc. */ { - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(slot != NULL); - - /* clear out the slot first */ - ExecClearTuple(slot); - - /* ---------------- - * store the new tuple into the specified slot and - * return the slot into which we stored the tuple. - * ---------------- - */ - slot->val = tuple; - slot->ttc_buffer = buffer; - slot->ttc_shouldFree = shouldFree; - - return slot; + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(slot != NULL); + + /* clear out the slot first */ + ExecClearTuple(slot); + + /* ---------------- + * store the new tuple into the specified slot and + * return the slot into which we stored the tuple. + * ---------------- + */ + slot->val = tuple; + slot->ttc_buffer = buffer; + slot->ttc_shouldFree = shouldFree; + + return slot; } /* -------------------------------- - * ExecClearTuple + * ExecClearTuple * - * This function is used to clear out a slot in the tuple table. + * This function is used to clear out a slot in the tuple table. * -------------------------------- */ -TupleTableSlot* /* return: slot passed */ -ExecClearTuple(TupleTableSlot* slot) /* slot in which to store tuple */ +TupleTableSlot * /* return: slot passed */ +ExecClearTuple(TupleTableSlot * slot) /* slot in which to store tuple */ { - HeapTuple oldtuple; /* prior contents of slot */ - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(slot != NULL); - - /* ---------------- - * get information from the tuple table - * ---------------- - */ - oldtuple = slot->val; - - /* ---------------- - * free the old contents of the specified slot if necessary. - * ---------------- - */ - if (slot->ttc_shouldFree && oldtuple != NULL) { + HeapTuple oldtuple; /* prior contents of slot */ + /* ---------------- - * since a tuple may contain a pointer to - * lock information allocated along with the - * tuple, we have to be careful to free any - * rule locks also -cim 1/17/90 + * sanity checks * ---------------- */ - pfree(oldtuple); - } - - /* ---------------- - * store NULL into the specified slot and return the slot. - * - also set buffer to InvalidBuffer -cim 3/14/91 - * ---------------- - */ - slot->val = (HeapTuple)NULL; - - if (BufferIsValid(slot->ttc_buffer)) - ReleaseBuffer(slot->ttc_buffer); - - slot->ttc_buffer = InvalidBuffer; - slot->ttc_shouldFree = true; - - return slot; + Assert(slot != NULL); + + /* ---------------- + * get information from the tuple table + * ---------------- + */ + oldtuple = slot->val; + + /* ---------------- + * free the old contents of the specified slot if necessary. + * ---------------- + */ + if (slot->ttc_shouldFree && oldtuple != NULL) + { + /* ---------------- + * since a tuple may contain a pointer to + * lock information allocated along with the + * tuple, we have to be careful to free any + * rule locks also -cim 1/17/90 + * ---------------- + */ + pfree(oldtuple); + } + + /* ---------------- + * store NULL into the specified slot and return the slot. + * - also set buffer to InvalidBuffer -cim 3/14/91 + * ---------------- + */ + slot->val = (HeapTuple) NULL; + + if (BufferIsValid(slot->ttc_buffer)) + ReleaseBuffer(slot->ttc_buffer); + + slot->ttc_buffer = InvalidBuffer; + slot->ttc_shouldFree = true; + + return slot; } /* -------------------------------- - * ExecSlotPolicy + * ExecSlotPolicy * - * This function is used to get the call/don't call pfree - * setting of a slot. Most executor routines don't need this. - * It's only when you do tricky things like marking tuples for - * merge joins that you need to diddle the slot policy. + * This function is used to get the call/don't call pfree + * setting of a slot. Most executor routines don't need this. + * It's only when you do tricky things like marking tuples for + * merge joins that you need to diddle the slot policy. * -------------------------------- */ #ifdef NOT_USED -bool /* return: slot policy */ -ExecSlotPolicy(TupleTableSlot* slot) /* slot to inspect */ +bool /* return: slot policy */ +ExecSlotPolicy(TupleTableSlot * slot) /* slot to inspect */ { - return slot->ttc_shouldFree; + return slot->ttc_shouldFree; } + #endif /* -------------------------------- - * ExecSetSlotPolicy + * ExecSetSlotPolicy * - * This function is used to change the call/don't call pfree - * setting of a slot. Most executor routines don't need this. - * It's only when you do tricky things like marking tuples for - * merge joins that you need to diddle the slot policy. + * This function is used to change the call/don't call pfree + * setting of a slot. Most executor routines don't need this. + * It's only when you do tricky things like marking tuples for + * merge joins that you need to diddle the slot policy. * -------------------------------- */ -bool /* return: old slot policy */ -ExecSetSlotPolicy(TupleTableSlot* slot, /* slot to change */ - bool shouldFree) /* true if we call pfree() when we gc. */ +bool /* return: old slot policy */ +ExecSetSlotPolicy(TupleTableSlot * slot, /* slot to change */ + bool shouldFree) /* true if we call pfree() when we + * gc. */ { - bool old_shouldFree = slot->ttc_shouldFree; - slot->ttc_shouldFree = shouldFree; + bool old_shouldFree = slot->ttc_shouldFree; - return old_shouldFree; + slot->ttc_shouldFree = shouldFree; + + return old_shouldFree; } /* -------------------------------- - * ExecSlotDescriptor + * ExecSlotDescriptor * - * This function is used to get the tuple descriptor associated - * with the slot's tuple. + * This function is used to get the tuple descriptor associated + * with the slot's tuple. * * Now a macro in tuptable.h -mer 5 March 1992 * -------------------------------- */ /* -------------------------------- - * ExecSetSlotDescriptor + * ExecSetSlotDescriptor * - * This function is used to set the tuple descriptor associated - * with the slot's tuple. + * This function is used to set the tuple descriptor associated + * with the slot's tuple. * -------------------------------- */ -TupleDesc /* return: old slot tuple descriptor */ -ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */ - TupleDesc tupdesc) /* tuple descriptor */ +TupleDesc /* return: old slot tuple descriptor */ +ExecSetSlotDescriptor(TupleTableSlot * slot, /* slot to change */ + TupleDesc tupdesc) /* tuple descriptor */ { - TupleDesc old_tupdesc = slot->ttc_tupleDescriptor; + TupleDesc old_tupdesc = slot->ttc_tupleDescriptor; - slot->ttc_tupleDescriptor = tupdesc; - return old_tupdesc; + slot->ttc_tupleDescriptor = tupdesc; + return old_tupdesc; } /* -------------------------------- - * ExecSetSlotDescriptorIsNew + * ExecSetSlotDescriptorIsNew * - * This function is used to change the setting of the "isNew" flag + * This function is used to change the setting of the "isNew" flag * -------------------------------- */ void -ExecSetSlotDescriptorIsNew(TupleTableSlot *slot,/* slot to change */ - bool isNew) /* "isNew" setting */ +ExecSetSlotDescriptorIsNew(TupleTableSlot * slot, /* slot to change */ + bool isNew) /* "isNew" setting */ { - slot->ttc_descIsNew = isNew; + slot->ttc_descIsNew = isNew; } /* -------------------------------- - * ExecSetNewSlotDescriptor + * ExecSetNewSlotDescriptor * - * This function is used to set the tuple descriptor associated - * with the slot's tuple, and set the "isNew" flag at the same time. + * This function is used to set the tuple descriptor associated + * with the slot's tuple, and set the "isNew" flag at the same time. * -------------------------------- */ #ifdef NOT_USED -TupleDesc /* return: old slot tuple descriptor */ -ExecSetNewSlotDescriptor(TupleTableSlot *slot, /* slot to change */ - TupleDesc tupdesc) /* tuple descriptor */ +TupleDesc /* return: old slot tuple descriptor */ +ExecSetNewSlotDescriptor(TupleTableSlot * slot, /* slot to change */ + TupleDesc tupdesc) /* tuple descriptor */ { - TupleDesc old_tupdesc = slot->ttc_tupleDescriptor; - slot->ttc_tupleDescriptor = tupdesc; - slot->ttc_descIsNew = true; - - return old_tupdesc; + TupleDesc old_tupdesc = slot->ttc_tupleDescriptor; + + slot->ttc_tupleDescriptor = tupdesc; + slot->ttc_descIsNew = true; + + return old_tupdesc; } + #endif /* -------------------------------- - * ExecSlotBuffer + * ExecSlotBuffer * - * This function is used to get the tuple descriptor associated - * with the slot's tuple. Be very careful with this as it does not - * balance the reference counts. If the buffer returned is stored - * someplace else, then also use ExecIncrSlotBufferRefcnt(). + * This function is used to get the tuple descriptor associated + * with the slot's tuple. Be very careful with this as it does not + * balance the reference counts. If the buffer returned is stored + * someplace else, then also use ExecIncrSlotBufferRefcnt(). * * Now a macro in tuptable.h * -------------------------------- */ /* -------------------------------- - * ExecSetSlotBuffer + * ExecSetSlotBuffer * - * This function is used to set the tuple descriptor associated - * with the slot's tuple. Be very careful with this as it does not - * balance the reference counts. If we're using this then we should - * also use ExecIncrSlotBufferRefcnt(). + * This function is used to set the tuple descriptor associated + * with the slot's tuple. Be very careful with this as it does not + * balance the reference counts. If we're using this then we should + * also use ExecIncrSlotBufferRefcnt(). * -------------------------------- */ #ifdef NOT_USED -Buffer /* return: old slot buffer */ -ExecSetSlotBuffer(TupleTableSlot *slot, /* slot to change */ - Buffer b) /* tuple descriptor */ +Buffer /* return: old slot buffer */ +ExecSetSlotBuffer(TupleTableSlot * slot, /* slot to change */ + Buffer b) /* tuple descriptor */ { - Buffer oldb = slot->ttc_buffer; - slot->ttc_buffer = b; - - return oldb; + Buffer oldb = slot->ttc_buffer; + + slot->ttc_buffer = b; + + return oldb; } + #endif /* -------------------------------- - * ExecIncrSlotBufferRefcnt + * ExecIncrSlotBufferRefcnt * - * When we pass around buffers in the tuple table, we have to - * be careful to increment reference counts appropriately. - * This is used mainly in the mergejoin code. + * When we pass around buffers in the tuple table, we have to + * be careful to increment reference counts appropriately. + * This is used mainly in the mergejoin code. * -------------------------------- */ void -ExecIncrSlotBufferRefcnt(TupleTableSlot *slot) /* slot to bump refcnt */ +ExecIncrSlotBufferRefcnt(TupleTableSlot * slot) /* slot to bump refcnt */ { -/* Buffer b = SlotBuffer((TupleTableSlot*) slot); */ - Buffer b = slot->ttc_buffer; - if (BufferIsValid(b)) - IncrBufferRefCount(b); +/* Buffer b = SlotBuffer((TupleTableSlot*) slot); */ + Buffer b = slot->ttc_buffer; + + if (BufferIsValid(b)) + IncrBufferRefCount(b); } /* ---------------------------------------------------------------- - * tuple table slot status predicates + * tuple table slot status predicates * ---------------------------------------------------------------- */ /* ---------------- - * TupIsNull + * TupIsNull * - * This is used mainly to detect when there are no more - * tuples to process. + * This is used mainly to detect when there are no more + * tuples to process. * ---------------- */ -bool /* return: true if tuple in slot is NULL */ -TupIsNull(TupleTableSlot* slot) /* slot to check */ +bool /* return: true if tuple in slot is NULL */ +TupIsNull(TupleTableSlot * slot) /* slot to check */ { - HeapTuple tuple; /* contents of slot (returned) */ - - /* ---------------- - * if the slot itself is null then we return true - * ---------------- - */ - if (slot == NULL) - return true; - - /* ---------------- - * get information from the slot and return true or - * false depending on the contents of the slot. - * ---------------- - */ - tuple = slot->val; - - return - (tuple == NULL ? true : false); + HeapTuple tuple; /* contents of slot (returned) */ + + /* ---------------- + * if the slot itself is null then we return true + * ---------------- + */ + if (slot == NULL) + return true; + + /* ---------------- + * get information from the slot and return true or + * false depending on the contents of the slot. + * ---------------- + */ + tuple = slot->val; + + return + (tuple == NULL ? true : false); } /* -------------------------------- - * ExecSlotDescriptorIsNew + * ExecSlotDescriptorIsNew * - * This function is used to check if the tuple descriptor - * associated with this slot has just changed. ie: we are - * now storing a new type of tuple in this slot + * This function is used to check if the tuple descriptor + * associated with this slot has just changed. ie: we are + * now storing a new type of tuple in this slot * -------------------------------- */ #ifdef NOT_USED -bool /* return: descriptor "is new" */ -ExecSlotDescriptorIsNew(TupleTableSlot *slot) /* slot to inspect */ +bool /* return: descriptor "is new" */ +ExecSlotDescriptorIsNew(TupleTableSlot * slot) /* slot to inspect */ { -/* bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot*) slot); - return isNew; */ - return slot->ttc_descIsNew; +/* bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot*) slot); + return isNew; */ + return slot->ttc_descIsNew; } + #endif /* ---------------------------------------------------------------- - * convenience initialization routines + * convenience initialization routines * ---------------------------------------------------------------- */ /* -------------------------------- - * ExecInit{Result,Scan,Raw,Marked,Outer,Hash}TupleSlot + * ExecInit{Result,Scan,Raw,Marked,Outer,Hash}TupleSlot * - * These are convenience routines to initialize the specfied slot - * in nodes inheriting the appropriate state. + * These are convenience routines to initialize the specfied slot + * in nodes inheriting the appropriate state. * -------------------------------- */ #define INIT_SLOT_DEFS \ - TupleTable tupleTable; \ - TupleTableSlot* slot - + TupleTable tupleTable; \ + TupleTableSlot* slot + #define INIT_SLOT_ALLOC \ - tupleTable = (TupleTable) estate->es_tupleTable; \ - slot = ExecAllocTableSlot(tupleTable); \ - slot->val = (HeapTuple)NULL; \ - slot->ttc_shouldFree = true; \ - slot->ttc_tupleDescriptor = (TupleDesc)NULL; \ - slot->ttc_whichplan = -1;\ - slot->ttc_descIsNew = true; + tupleTable = (TupleTable) estate->es_tupleTable; \ + slot = ExecAllocTableSlot(tupleTable); \ + slot->val = (HeapTuple)NULL; \ + slot->ttc_shouldFree = true; \ + slot->ttc_tupleDescriptor = (TupleDesc)NULL; \ + slot->ttc_whichplan = -1;\ + slot->ttc_descIsNew = true; /* ---------------- - * ExecInitResultTupleSlot + * ExecInitResultTupleSlot * ---------------- */ void -ExecInitResultTupleSlot(EState *estate, CommonState *commonstate) +ExecInitResultTupleSlot(EState * estate, CommonState * commonstate) { - INIT_SLOT_DEFS; - INIT_SLOT_ALLOC; - commonstate->cs_ResultTupleSlot = (TupleTableSlot *) slot; + INIT_SLOT_DEFS; + INIT_SLOT_ALLOC; + commonstate->cs_ResultTupleSlot = (TupleTableSlot *) slot; } /* ---------------- - * ExecInitScanTupleSlot + * ExecInitScanTupleSlot * ---------------- */ void -ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate) +ExecInitScanTupleSlot(EState * estate, CommonScanState * commonscanstate) { - INIT_SLOT_DEFS; - INIT_SLOT_ALLOC; - commonscanstate->css_ScanTupleSlot = (TupleTableSlot *)slot; + INIT_SLOT_DEFS; + INIT_SLOT_ALLOC; + commonscanstate->css_ScanTupleSlot = (TupleTableSlot *) slot; } /* ---------------- - * ExecInitMarkedTupleSlot + * ExecInitMarkedTupleSlot * ---------------- */ void -ExecInitMarkedTupleSlot(EState *estate, MergeJoinState *mergestate) +ExecInitMarkedTupleSlot(EState * estate, MergeJoinState * mergestate) { - INIT_SLOT_DEFS; - INIT_SLOT_ALLOC; - mergestate->mj_MarkedTupleSlot = (TupleTableSlot *) slot; + INIT_SLOT_DEFS; + INIT_SLOT_ALLOC; + mergestate->mj_MarkedTupleSlot = (TupleTableSlot *) slot; } /* ---------------- - * ExecInitOuterTupleSlot + * ExecInitOuterTupleSlot * ---------------- */ void -ExecInitOuterTupleSlot(EState *estate, HashJoinState *hashstate) +ExecInitOuterTupleSlot(EState * estate, HashJoinState * hashstate) { - INIT_SLOT_DEFS; - INIT_SLOT_ALLOC; - hashstate->hj_OuterTupleSlot = slot; + INIT_SLOT_DEFS; + INIT_SLOT_ALLOC; + hashstate->hj_OuterTupleSlot = slot; } /* ---------------- - * ExecInitHashTupleSlot + * ExecInitHashTupleSlot * ---------------- */ #ifdef NOT_USED void -ExecInitHashTupleSlot(EState *estate, HashJoinState *hashstate) +ExecInitHashTupleSlot(EState * estate, HashJoinState * hashstate) { - INIT_SLOT_DEFS; - INIT_SLOT_ALLOC; - hashstate->hj_HashTupleSlot = slot; + INIT_SLOT_DEFS; + INIT_SLOT_ALLOC; + hashstate->hj_HashTupleSlot = slot; } + #endif static TupleTableSlot * -NodeGetResultTupleSlot(Plan *node) +NodeGetResultTupleSlot(Plan * node) { - TupleTableSlot *slot; - - switch(nodeTag(node)) { - - case T_Result: - { - ResultState *resstate = ((Result *)node)->resstate; - slot = resstate->cstate.cs_ResultTupleSlot; - } - break; - - case T_SeqScan: - { - CommonScanState *scanstate = ((SeqScan *)node)->scanstate; - slot = scanstate->cstate.cs_ResultTupleSlot; - } - break; - - case T_NestLoop: - { - NestLoopState *nlstate = ((NestLoop *)node)->nlstate; - slot = nlstate->jstate.cs_ResultTupleSlot; - } - break; - - case T_Append: - { - Append *n = (Append *)node; - AppendState *unionstate; - List *unionplans; - int whichplan; - Plan *subplan; - - unionstate = n->unionstate; - unionplans = n->unionplans; - whichplan = unionstate->as_whichplan; - - subplan = (Plan*) nth(whichplan, unionplans); - slot = NodeGetResultTupleSlot(subplan); - break; - } - - case T_IndexScan: - { - CommonScanState *scanstate = ((IndexScan *)node)->scan.scanstate; - slot = scanstate->cstate.cs_ResultTupleSlot; - } - break; - - case T_Material: - { - MaterialState *matstate = ((Material *)node)->matstate; - slot = matstate->csstate.css_ScanTupleSlot; - } - break; - - case T_Sort: - { - SortState *sortstate = ((Sort *)node)->sortstate; - slot = sortstate->csstate.css_ScanTupleSlot; - } - break; - - case T_Agg: - { - AggState *aggstate = ((Agg *)node)->aggstate; - slot = aggstate->csstate.cstate.cs_ResultTupleSlot; - } - break; - - case T_Group: - { - GroupState *grpstate = ((Group *)node)->grpstate; - slot = grpstate->csstate.cstate.cs_ResultTupleSlot; - } - break; - - case T_Hash: - { - HashState *hashstate = ((Hash *)node)->hashstate; - slot = hashstate->cstate.cs_ResultTupleSlot; - } - break; - - case T_Unique: - { - UniqueState *uniquestate = ((Unique *)node)->uniquestate; - slot = uniquestate->cs_ResultTupleSlot; - } - break; - - case T_MergeJoin: - { - MergeJoinState *mergestate = ((MergeJoin *)node)->mergestate; - slot = mergestate->jstate.cs_ResultTupleSlot; - } - break; - - case T_HashJoin: + TupleTableSlot *slot; + + switch (nodeTag(node)) { - HashJoinState *hashjoinstate = ((HashJoin *)node)->hashjoinstate; - slot = hashjoinstate->jstate.cs_ResultTupleSlot; + + case T_Result: + { + ResultState *resstate = ((Result *) node)->resstate; + + slot = resstate->cstate.cs_ResultTupleSlot; + } + break; + + case T_SeqScan: + { + CommonScanState *scanstate = ((SeqScan *) node)->scanstate; + + slot = scanstate->cstate.cs_ResultTupleSlot; + } + break; + + case T_NestLoop: + { + NestLoopState *nlstate = ((NestLoop *) node)->nlstate; + + slot = nlstate->jstate.cs_ResultTupleSlot; + } + break; + + case T_Append: + { + Append *n = (Append *) node; + AppendState *unionstate; + List *unionplans; + int whichplan; + Plan *subplan; + + unionstate = n->unionstate; + unionplans = n->unionplans; + whichplan = unionstate->as_whichplan; + + subplan = (Plan *) nth(whichplan, unionplans); + slot = NodeGetResultTupleSlot(subplan); + break; + } + + case T_IndexScan: + { + CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate; + + slot = scanstate->cstate.cs_ResultTupleSlot; + } + break; + + case T_Material: + { + MaterialState *matstate = ((Material *) node)->matstate; + + slot = matstate->csstate.css_ScanTupleSlot; + } + break; + + case T_Sort: + { + SortState *sortstate = ((Sort *) node)->sortstate; + + slot = sortstate->csstate.css_ScanTupleSlot; + } + break; + + case T_Agg: + { + AggState *aggstate = ((Agg *) node)->aggstate; + + slot = aggstate->csstate.cstate.cs_ResultTupleSlot; + } + break; + + case T_Group: + { + GroupState *grpstate = ((Group *) node)->grpstate; + + slot = grpstate->csstate.cstate.cs_ResultTupleSlot; + } + break; + + case T_Hash: + { + HashState *hashstate = ((Hash *) node)->hashstate; + + slot = hashstate->cstate.cs_ResultTupleSlot; + } + break; + + case T_Unique: + { + UniqueState *uniquestate = ((Unique *) node)->uniquestate; + + slot = uniquestate->cs_ResultTupleSlot; + } + break; + + case T_MergeJoin: + { + MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate; + + slot = mergestate->jstate.cs_ResultTupleSlot; + } + break; + + case T_HashJoin: + { + HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate; + + slot = hashjoinstate->jstate.cs_ResultTupleSlot; + } + break; + + case T_Tee: + { + TeeState *teestate = ((Tee *) node)->teestate; + + slot = teestate->cstate.cs_ResultTupleSlot; + } + break; + + default: + /* ---------------- + * should never get here + * ---------------- + */ + elog(WARN, "NodeGetResultTupleSlot: node not yet supported: %d ", + nodeTag(node)); + + return NULL; } - break; - - case T_Tee: - { - TeeState *teestate = ((Tee*)node)->teestate; - slot = teestate->cstate.cs_ResultTupleSlot; - } - break; - - default: - /* ---------------- - * should never get here - * ---------------- - */ - elog(WARN, "NodeGetResultTupleSlot: node not yet supported: %d ", - nodeTag(node)); - - return NULL; - } - return slot; + return slot; } /* ---------------------------------------------------------------- - * ExecGetTupType + * ExecGetTupType * - * this gives you the tuple descriptor for tuples returned - * by this node. I really wish I could ditch this routine, - * but since not all nodes store their type info in the same - * place, we have to do something special for each node type. + * this gives you the tuple descriptor for tuples returned + * by this node. I really wish I could ditch this routine, + * but since not all nodes store their type info in the same + * place, we have to do something special for each node type. * - * Soon, the system will have to adapt to deal with changing - * tuple descriptors as we deal with dynamic tuple types - * being returned from procedure nodes. Perhaps then this - * routine can be retired. -cim 6/3/91 + * Soon, the system will have to adapt to deal with changing + * tuple descriptors as we deal with dynamic tuple types + * being returned from procedure nodes. Perhaps then this + * routine can be retired. -cim 6/3/91 * * old comments - * This routine just gets the type information out of the - * node's state. If you already have a node's state, you - * can get this information directly, but this is a useful - * routine if you want to get the type information from - * the node's inner or outer subplan easily without having - * to inspect the subplan.. -cim 10/16/89 + * This routine just gets the type information out of the + * node's state. If you already have a node's state, you + * can get this information directly, but this is a useful + * routine if you want to get the type information from + * the node's inner or outer subplan easily without having + * to inspect the subplan.. -cim 10/16/89 * - * Assume that for existential nodes, we get the targetlist out - * of the right node's targetlist + * Assume that for existential nodes, we get the targetlist out + * of the right node's targetlist * ---------------------------------------------------------------- */ TupleDesc -ExecGetTupType(Plan *node) +ExecGetTupType(Plan * node) { - TupleTableSlot *slot; - TupleDesc tupType; - - if (node == NULL) - return NULL; - - slot = NodeGetResultTupleSlot(node); - tupType = slot->ttc_tupleDescriptor; - return tupType; + TupleTableSlot *slot; + TupleDesc tupType; + + if (node == NULL) + return NULL; + + slot = NodeGetResultTupleSlot(node); + tupType = slot->ttc_tupleDescriptor; + return tupType; } /* TupleDesc -ExecCopyTupType(TupleDesc td, int natts) +ExecCopyTupType(TupleDesc td, int natts) { - TupleDesc newTd; - int i; - - newTd = CreateTemplateTupleDesc(natts); - i = 0; - while (i < natts) - { - newTd[i] = - (AttributeTupleForm)palloc(sizeof(FormData_pg_attribute)); - memmove(newTd[i], td[i], sizeof(FormData_pg_attribute)); - i++; - } - return newTd; + TupleDesc newTd; + int i; + + newTd = CreateTemplateTupleDesc(natts); + i = 0; + while (i < natts) + { + newTd[i] = + (AttributeTupleForm)palloc(sizeof(FormData_pg_attribute)); + memmove(newTd[i], td[i], sizeof(FormData_pg_attribute)); + i++; + } + return newTd; } */ /* ---------------------------------------------------------------- - * ExecTypeFromTL - * - * Currently there are about 4 different places where we create - * TupleDescriptors. They should all be merged, or perhaps - * be rewritten to call BuildDesc(). - * - * old comments - * Forms attribute type info from the target list in the node. - * It assumes all domains are individually specified in the target list. - * It fails if the target list contains something like Emp.all - * which represents all the attributes from EMP relation. - * - * Conditions: - * The inner and outer subtrees should be initialized because it - * might be necessary to know the type infos of the subtrees. + * ExecTypeFromTL + * + * Currently there are about 4 different places where we create + * TupleDescriptors. They should all be merged, or perhaps + * be rewritten to call BuildDesc(). + * + * old comments + * Forms attribute type info from the target list in the node. + * It assumes all domains are individually specified in the target list. + * It fails if the target list contains something like Emp.all + * which represents all the attributes from EMP relation. + * + * Conditions: + * The inner and outer subtrees should be initialized because it + * might be necessary to know the type infos of the subtrees. * ---------------------------------------------------------------- */ TupleDesc -ExecTypeFromTL(List *targetList) +ExecTypeFromTL(List * targetList) { - List *tlcdr; - TupleDesc typeInfo; - Resdom *resdom; - Oid restype; - int len; - - /* ---------------- - * examine targetlist - if empty then return NULL - * ---------------- - */ - len = ExecTargetListLength(targetList); - - if (len == 0) - return NULL; - - /* ---------------- - * allocate a new typeInfo - * ---------------- - */ - typeInfo = CreateTemplateTupleDesc(len); - - /* ---------------- - * notes: get resdom from (resdom expr) - * get_typbyval comes from src/lib/l-lisp/lsyscache.c - * ---------------- - */ - tlcdr = targetList; - while (tlcdr != NIL) { - TargetEntry *tle = lfirst(tlcdr); - if (tle->resdom != NULL) { - resdom = tle->resdom; - restype = resdom->restype; - - TupleDescInitEntry(typeInfo, - resdom->resno, - resdom->resname, - /* fix for SELECT NULL ... */ - get_id_typname(restype?restype:UNKNOWNOID), - 0, - false); + List *tlcdr; + TupleDesc typeInfo; + Resdom *resdom; + Oid restype; + int len; + + /* ---------------- + * examine targetlist - if empty then return NULL + * ---------------- + */ + len = ExecTargetListLength(targetList); + + if (len == 0) + return NULL; + + /* ---------------- + * allocate a new typeInfo + * ---------------- + */ + typeInfo = CreateTemplateTupleDesc(len); + + /* ---------------- + * notes: get resdom from (resdom expr) + * get_typbyval comes from src/lib/l-lisp/lsyscache.c + * ---------------- + */ + tlcdr = targetList; + while (tlcdr != NIL) + { + TargetEntry *tle = lfirst(tlcdr); + + if (tle->resdom != NULL) + { + resdom = tle->resdom; + restype = resdom->restype; + + TupleDescInitEntry(typeInfo, + resdom->resno, + resdom->resname, + /* fix for SELECT NULL ... */ + get_id_typname(restype ? restype : UNKNOWNOID), + 0, + false); /* - ExecSetTypeInfo(resdom->resno - 1, - typeInfo, - (Oid) restype, - resdom->resno, - resdom->reslen, - resdom->resname->data, - get_typbyval(restype), - get_typalign(restype)); + ExecSetTypeInfo(resdom->resno - 1, + typeInfo, + (Oid) restype, + resdom->resno, + resdom->reslen, + resdom->resname->data, + get_typbyval(restype), + get_typalign(restype)); */ - } - else { - Resdom *fjRes; - List *fjTlistP; - List *fjList = lfirst(tlcdr); + } + else + { + Resdom *fjRes; + List *fjTlistP; + List *fjList = lfirst(tlcdr); + #ifdef SETS_FIXED - TargetEntry *tle; - Fjoin *fjNode = ((TargetEntry *)lfirst(fjList))->fjoin; + TargetEntry *tle; + Fjoin *fjNode = ((TargetEntry *) lfirst(fjList))->fjoin; - tle = fjNode->fj_innerNode; /* ??? */ + tle = fjNode->fj_innerNode; /* ??? */ #endif - fjRes = tle->resdom; - restype = fjRes->restype; - - TupleDescInitEntry(typeInfo, - fjRes->resno, - fjRes->resname, - get_id_typname(restype), - 0, - false); + fjRes = tle->resdom; + restype = fjRes->restype; + + TupleDescInitEntry(typeInfo, + fjRes->resno, + fjRes->resname, + get_id_typname(restype), + 0, + false); /* - ExecSetTypeInfo(fjRes->resno - 1, - typeInfo, - (Oid) restype, - fjRes->resno, - fjRes->reslen, - (char *) fjRes->resname, - get_typbyval(restype), - get_typalign(restype)); + ExecSetTypeInfo(fjRes->resno - 1, + typeInfo, + (Oid) restype, + fjRes->resno, + fjRes->reslen, + (char *) fjRes->resname, + get_typbyval(restype), + get_typalign(restype)); */ - - foreach(fjTlistP, lnext(fjList)) { - TargetEntry *fjTle = lfirst(fjTlistP); - - fjRes = fjTle->resdom; - - TupleDescInitEntry(typeInfo, - fjRes->resno, - fjRes->resname, - get_id_typname(restype), - 0, - false); - + + foreach(fjTlistP, lnext(fjList)) + { + TargetEntry *fjTle = lfirst(fjTlistP); + + fjRes = fjTle->resdom; + + TupleDescInitEntry(typeInfo, + fjRes->resno, + fjRes->resname, + get_id_typname(restype), + 0, + false); + /* - ExecSetTypeInfo(fjRes->resno - 1, - typeInfo, - (Oid) fjRes->restype, - fjRes->resno, - fjRes->reslen, - (char *) fjRes->resname, - get_typbyval(fjRes->restype), - get_typalign(fjRes->restype)); + ExecSetTypeInfo(fjRes->resno - 1, + typeInfo, + (Oid) fjRes->restype, + fjRes->resno, + fjRes->reslen, + (char *) fjRes->resname, + get_typbyval(fjRes->restype), + get_typalign(fjRes->restype)); */ - } - } - - tlcdr = lnext(tlcdr); - } - - return typeInfo; -} + } + } + tlcdr = lnext(tlcdr); + } + return typeInfo; +} |