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

📄 exectuples.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
 *			Obtain a copy of a slot's physical tuple.  The copy is *			palloc'd in the current memory context. * *		This works even if the slot contains a virtual tuple; *		however the "system columns" of the result will not be meaningful. * -------------------------------- */HeapTupleExecCopySlotTuple(TupleTableSlot *slot){	/*	 * sanity checks	 */	Assert(slot != NULL);	Assert(!slot->tts_isempty);	/*	 * If we have a physical tuple then just copy it.	 */	if (slot->tts_tuple)		return heap_copytuple(slot->tts_tuple);	/*	 * Otherwise we need to build a tuple from the Datum array.	 */	return heap_form_tuple(slot->tts_tupleDescriptor,						   slot->tts_values,						   slot->tts_isnull);}/* -------------------------------- *		ExecFetchSlotTuple *			Fetch the slot's physical tuple. * *		If the slot contains a virtual tuple, we convert it to physical *		form.  The slot retains ownership of the physical tuple. * * The difference between this and ExecMaterializeSlot() is that this * does not guarantee that the contained tuple is local storage. * Hence, the result must be treated as read-only. * -------------------------------- */HeapTupleExecFetchSlotTuple(TupleTableSlot *slot){	/*	 * sanity checks	 */	Assert(slot != NULL);	Assert(!slot->tts_isempty);	/*	 * If we have a physical tuple then just return it.	 */	if (slot->tts_tuple)		return slot->tts_tuple;	/*	 * Otherwise materialize the slot...	 */	return ExecMaterializeSlot(slot);}/* -------------------------------- *		ExecMaterializeSlot *			Force a slot into the "materialized" state. * *		This causes the slot's tuple to be a local copy not dependent on *		any external storage.  A pointer to the contained tuple is returned. * *		A typical use for this operation is to prepare a computed tuple *		for being stored on disk.  The original data may or may not be *		virtual, but in any case we need a private copy for heap_insert *		to scribble on. * -------------------------------- */HeapTupleExecMaterializeSlot(TupleTableSlot *slot){	HeapTuple	newTuple;	MemoryContext oldContext;	/*	 * sanity checks	 */	Assert(slot != NULL);	Assert(!slot->tts_isempty);	/*	 * If we have a physical tuple, and it's locally palloc'd, we have nothing	 * to do.	 */	if (slot->tts_tuple && slot->tts_shouldFree)		return slot->tts_tuple;	/*	 * Otherwise, copy or build a tuple, and then store it as the new slot	 * value.  (Note: tts_nvalid will be reset to zero here.  There are cases	 * in which this could be optimized but it's probably not worth worrying	 * about.)	 *	 * We may be called in a context that is shorter-lived than the tuple	 * slot, but we have to ensure that the materialized tuple will survive	 * anyway.	 */	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);	newTuple = ExecCopySlotTuple(slot);	MemoryContextSwitchTo(oldContext);	ExecStoreTuple(newTuple, slot, InvalidBuffer, true);	return slot->tts_tuple;}/* -------------------------------- *		ExecCopySlot *			Copy the source slot's contents into the destination slot. * *		The destination acquires a private copy that will not go away *		if the source is cleared. * *		The caller must ensure the slots have compatible tupdescs. * -------------------------------- */TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot){	HeapTuple	newTuple;	MemoryContext oldContext;	/*	 * There might be ways to optimize this when the source is virtual, but	 * for now just always build a physical copy.  Make sure it is in the	 * right context.	 */	oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);	newTuple = ExecCopySlotTuple(srcslot);	MemoryContextSwitchTo(oldContext);	return ExecStoreTuple(newTuple, dstslot, InvalidBuffer, true);}/* ---------------------------------------------------------------- *				convenience initialization routines * ---------------------------------------------------------------- *//* -------------------------------- *		ExecInit{Result,Scan,Extra}TupleSlot * *		These are convenience routines to initialize the specified slot *		in nodes inheriting the appropriate state.	ExecInitExtraTupleSlot *		is used for initializing special-purpose slots. * -------------------------------- *//* ---------------- *		ExecInitResultTupleSlot * ---------------- */voidExecInitResultTupleSlot(EState *estate, PlanState *planstate){	planstate->ps_ResultTupleSlot = ExecAllocTableSlot(estate->es_tupleTable);}/* ---------------- *		ExecInitScanTupleSlot * ---------------- */voidExecInitScanTupleSlot(EState *estate, ScanState *scanstate){	scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(estate->es_tupleTable);}/* ---------------- *		ExecInitExtraTupleSlot * ---------------- */TupleTableSlot *ExecInitExtraTupleSlot(EState *estate){	return ExecAllocTableSlot(estate->es_tupleTable);}/* ---------------- *		ExecInitNullTupleSlot * * Build a slot containing an all-nulls tuple of the given type. * This is used as a substitute for an input tuple when performing an * outer join. * ---------------- */TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType){	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate);	ExecSetSlotDescriptor(slot, tupType, false);	return ExecStoreAllNullTuple(slot);}/* ---------------------------------------------------------------- *		ExecTypeFromTL * *		Generate a tuple descriptor for the result tuple of a targetlist. *		(A parse/plan tlist must be passed, not an ExprState tlist.) *		Note that resjunk columns, if any, are included in the result. * *		Currently there are about 4 different places where we create *		TupleDescriptors.  They should all be merged, or perhaps *		be rewritten to call BuildDesc(). * ---------------------------------------------------------------- */TupleDescExecTypeFromTL(List *targetList, bool hasoid){	return ExecTypeFromTLInternal(targetList, hasoid, false);}/* ---------------------------------------------------------------- *		ExecCleanTypeFromTL * *		Same as above, but resjunk columns are omitted from the result. * ---------------------------------------------------------------- */TupleDescExecCleanTypeFromTL(List *targetList, bool hasoid){	return ExecTypeFromTLInternal(targetList, hasoid, true);}static TupleDescExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk){	TupleDesc	typeInfo;	ListCell   *l;	int			len;	int			cur_resno = 1;	if (skipjunk)		len = ExecCleanTargetListLength(targetList);	else		len = ExecTargetListLength(targetList);	typeInfo = CreateTemplateTupleDesc(len, hasoid);	foreach(l, targetList)	{		TargetEntry *tle = lfirst(l);		if (skipjunk && tle->resjunk)			continue;		TupleDescInitEntry(typeInfo,						   cur_resno++,						   tle->resname,						   exprType((Node *) tle->expr),						   exprTypmod((Node *) tle->expr),						   0);	}	return typeInfo;}/* * ExecTypeFromExprList - build a tuple descriptor from a list of Exprs * * Here we must make up an arbitrary set of field names. */TupleDescExecTypeFromExprList(List *exprList){	TupleDesc	typeInfo;	ListCell   *l;	int			cur_resno = 1;	char		fldname[NAMEDATALEN];	typeInfo = CreateTemplateTupleDesc(list_length(exprList), false);	foreach(l, exprList)	{		Node	   *e = lfirst(l);		sprintf(fldname, "f%d", cur_resno);		TupleDescInitEntry(typeInfo,						   cur_resno++,						   fldname,						   exprType(e),						   exprTypmod(e),						   0);	}	return typeInfo;}/* * BlessTupleDesc - make a completed tuple descriptor useful for SRFs * * Rowtype Datums returned by a function must contain valid type information. * This happens "for free" if the tupdesc came from a relcache entry, but * not if we have manufactured a tupdesc for a transient RECORD datatype. * In that case we have to notify typcache.c of the existence of the type. */TupleDescBlessTupleDesc(TupleDesc tupdesc){	if (tupdesc->tdtypeid == RECORDOID &&		tupdesc->tdtypmod < 0)		assign_record_type_typmod(tupdesc);	return tupdesc;				/* just for notational convenience */}/* * TupleDescGetSlot - Initialize a slot based on the supplied tupledesc * * Note: this is obsolete; it is sufficient to call BlessTupleDesc on * the tupdesc.  We keep it around just for backwards compatibility with * existing user-written SRFs. */TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc){	TupleTableSlot *slot;	/* The useful work is here */	BlessTupleDesc(tupdesc);	/* Make a standalone slot */	slot = MakeSingleTupleTableSlot(tupdesc);	/* Return the slot */	return slot;}/* * TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the * supplied TupleDesc. AttInMetadata can be used in conjunction with C strings * to produce a properly formed tuple. */AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc){	int			natts = tupdesc->natts;	int			i;	Oid			atttypeid;	Oid			attinfuncid;	FmgrInfo   *attinfuncinfo;	Oid		   *attioparams;	int32	   *atttypmods;	AttInMetadata *attinmeta;	attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));	/* "Bless" the tupledesc so that we can make rowtype datums with it */	attinmeta->tupdesc = BlessTupleDesc(tupdesc);	/*	 * Gather info needed later to call the "in" function for each attribute	 */	attinfuncinfo = (FmgrInfo *) palloc0(natts * sizeof(FmgrInfo));	attioparams = (Oid *) palloc0(natts * sizeof(Oid));	atttypmods = (int32 *) palloc0(natts * sizeof(int32));	for (i = 0; i < natts; i++)	{		/* Ignore dropped attributes */		if (!tupdesc->attrs[i]->attisdropped)		{			atttypeid = tupdesc->attrs[i]->atttypid;			getTypeInputInfo(atttypeid, &attinfuncid, &attioparams[i]);			fmgr_info(attinfuncid, &attinfuncinfo[i]);			atttypmods[i] = tupdesc->attrs[i]->atttypmod;		}	}	attinmeta->attinfuncs = attinfuncinfo;	attinmeta->attioparams = attioparams;	attinmeta->atttypmods = atttypmods;	return attinmeta;}/* * BuildTupleFromCStrings - build a HeapTuple given user data in C string form. * values is an array of C strings, one for each attribute of the return tuple. */HeapTupleBuildTupleFromCStrings(AttInMetadata *attinmeta, char **values){	TupleDesc	tupdesc = attinmeta->tupdesc;	int			natts = tupdesc->natts;	Datum	   *dvalues;	char	   *nulls;	int			i;	Oid			attioparam;	int32		atttypmod;	HeapTuple	tuple;	dvalues = (Datum *) palloc(natts * sizeof(Datum));	nulls = (char *) palloc(natts * sizeof(char));	/* Call the "in" function for each non-null, non-dropped attribute */	for (i = 0; i < natts; i++)	{		if (!tupdesc->attrs[i]->attisdropped)		{			/* Non-dropped attributes */			if (values[i] != NULL)			{				attioparam = attinmeta->attioparams[i];				atttypmod = attinmeta->atttypmods[i];				dvalues[i] = FunctionCall3(&attinmeta->attinfuncs[i],										   CStringGetDatum(values[i]),										   ObjectIdGetDatum(attioparam),										   Int32GetDatum(atttypmod));				nulls[i] = ' ';			}			else			{				dvalues[i] = (Datum) 0;				nulls[i] = 'n';			}		}		else		{			/* Handle dropped attributes by setting to NULL */			dvalues[i] = (Datum) 0;			nulls[i] = 'n';		}	}	/*	 * Form a tuple	 */	tuple = heap_formtuple(tupdesc, dvalues, nulls);	/*	 * Release locally palloc'd space.  XXX would probably be good to pfree	 * values of pass-by-reference datums, as well.	 */	pfree(dvalues);	pfree(nulls);	return tuple;}/* * Functions for sending tuples to the frontend (or other specified destination) * as though it is a SELECT result. These are used by utility commands that * need to project directly to the destination and don't need or want full * Table Function capability. Currently used by EXPLAIN and SHOW ALL */TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc){	TupOutputState *tstate;	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));	tstate->metadata = TupleDescGetAttInMetadata(tupdesc);	tstate->slot = MakeSingleTupleTableSlot(tupdesc);	tstate->dest = dest;	(*tstate->dest->rStartup) (tstate->dest, (int) CMD_SELECT, tupdesc);	return tstate;}/* * write a single tuple * * values is a list of the external C string representations of the values * to be projected. * * XXX This could be made more efficient, since in reality we probably only * need a virtual tuple. */voiddo_tup_output(TupOutputState *tstate, char **values){	/* build a tuple from the input strings using the tupdesc */	HeapTuple	tuple = BuildTupleFromCStrings(tstate->metadata, values);	/* put it in a slot */	ExecStoreTuple(tuple, tstate->slot, InvalidBuffer, true);	/* send the tuple to the receiver */	(*tstate->dest->receiveSlot) (tstate->slot, tstate->dest);	/* clean up */	ExecClearTuple(tstate->slot);}/* * write a chunk of text, breaking at newline characters * * NB: scribbles on its input! * * Should only be used with a single-TEXT-attribute tupdesc. */voiddo_text_output_multiline(TupOutputState *tstate, char *text){	while (*text)	{		char	   *eol;		eol = strchr(text, '\n');		if (eol)			*eol++ = '\0';		else			eol = text +strlen(text);		do_tup_output(tstate, &text);		text = eol;	}}voidend_tup_output(TupOutputState *tstate){	(*tstate->dest->rShutdown) (tstate->dest);	/* note that destroying the dest is not ours to do */	ExecDropSingleTupleTableSlot(tstate->slot);	/* XXX worth cleaning up the attinmetadata? */	pfree(tstate);}

⌨️ 快捷键说明

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