⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exectuples.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * 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 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: /usr/local/cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.25 1999/05/25 16:08:39 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES * *	 TABLE CREATE/DELETE *		ExecCreateTupleTable	- create a new tuple table *		ExecDestroyTupleTable	- destroy a 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(Macro) * *	 SLOT STATUS PREDICATES *		TupIsNull				- true when slot contains no tuple(Macro) *		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	  / * *	 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. * *		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. * *		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. * *		- 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. * *		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 * *		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. * */#include <string.h>#include "postgres.h"#include "executor/executor.h"#undef ExecStoreTuple#include "access/tupdesc.h"#include "catalog/pg_type.h"#include "parser/parse_type.h"#include "storage/bufmgr.h"#include "utils/palloc.h"#include "utils/lsyscache.h"static TupleTableSlot *NodeGetResultTupleSlot(Plan *node);/* ---------------------------------------------------------------- *				  tuple table create/delete functions * ---------------------------------------------------------------- *//* -------------------------------- *		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 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	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 * *		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(). * -------------------------------- */voidExecDestroyTupleTable(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);				}			}		}	/* ----------------	 *	finally free the tuple array and the table itself.	 * ----------------	 */	pfree(array);	pfree(table);}/* ---------------------------------------------------------------- *				  tuple table slot reservation functions * ---------------------------------------------------------------- *//* -------------------------------- *		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). * -------------------------------- */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);		 *		 * 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(ERROR, "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 * ---------------------------------------------------------------- *//* -------------------------------- *		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. * -------------------------------- */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;}/* -------------------------------- *		ExecClearTuple * *		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 */{	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)	{		/* ----------------		 *	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 * *		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_USEDbool							/* return: slot policy */ExecSlotPolicy(TupleTableSlot *slot)	/* slot to inspect */{	return slot->ttc_shouldFree;}/* -------------------------------- *		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. * -------------------------------- */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;	return old_shouldFree;}#endif/* -------------------------------- *		ExecSlotDescriptor * *		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 * *		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	old_tupdesc = slot->ttc_tupleDescriptor;	slot->ttc_tupleDescriptor = tupdesc;	return old_tupdesc;}/* -------------------------------- *		ExecSetSlotDescriptorIsNew * *		This function is used to change the setting of the "isNew" flag * -------------------------------- */voidExecSetSlotDescriptorIsNew(TupleTableSlot *slot,		/* slot to change */						   bool isNew)	/* "isNew" setting */{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -