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

📄 be-dumpdata.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * be-dumpdata.c *	  support for collection of returned tuples from an internal *	  PQ call into a backend buffer. * * Copyright (c) 1994, Regents of the University of California * *	$Id: be-dumpdata.c,v 1.25 1999/05/25 22:41:06 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES *		be_portalinit	 - initialize backend portal administration *		be_portalpush	 - add a portal to the top of the portal stack *		be_portalpop	 - remove portal on the top of the stack & return it *		be_currentportal - return the top portal on the portal stack *		be_newportal	 - return a new portal. *		be_portalinit	 - initialize backend portal expected to hold results. *		be_printtup		 - add a tuple to a backend portal * * NOTES *		Since backend user-defined operators can call queries *		which in turn call user-defined operators can call queries... *		we have to keep track of portals on a stack.  BeginCommand() *		puts portals on the stack and the PQ functions remove them. * */#include <string.h>#include <postgres.h>#include <lib/dllist.h>#include <libpq/libpq.h>#include <access/heapam.h>#include <access/htup.h>#include <storage/buf.h>#include <utils/memutils.h>#include <fmgr.h>#include <utils/mcxt.h>#include <utils/exc.h>#include <utils/syscache.h>#include <catalog/pg_type.h>#include <catalog/catalog.h>#include <access/printtup.h>/* ---------------- *		backend portal stack for recursive PQexec calls * ---------------- */static Dllist *be_portalstack;/* ---------------- *		be_portalinit - initialize backend portal administration * *		This is called once from InitPostgres() to initialize *		the portal stack. * ---------------- */voidbe_portalinit(void){	be_portalstack = DLNewList();}/* ---------------- *		be_portalpush - add a portal to the top of the portal stack * *		used by BeginCommand() * ---------------- */voidbe_portalpush(PortalEntry *entry){	DLAddTail(be_portalstack, DLNewElem(entry));}/* ---------------- *		be_portalpop - remove the portal on the top of the stack & return it * *		used by PQexec() * ---------------- */PortalEntry *be_portalpop(void){	PortalEntry *p;	Dlelem	   *elt;	elt = DLRemTail(be_portalstack);	p = (elt ? (PortalEntry *) DLE_VAL(elt) : NULL);	DLFreeElem(elt);	return p;}/* ---------------- *		be_currentportal - return the top portal on the portal stack * *		used by be_printtup() * ---------------- */PortalEntry *be_currentportal(void){	Dlelem	   *elt;	elt = DLGetTail(be_portalstack);	return elt ? (PortalEntry *) DLE_VAL(elt) : NULL;}/* ---------------- *		be_newportal - return a new portal. * *		If the user-defined function does not specify a portal name, *		we generate a unique one.  Names are generated from a combination *		of a postgres oid and an integer counter which is incremented *		every time we ask for a local portal. * *		used by BeginCommand() * ---------------- */static Oid	be_portaloid;static u_int be_portalcnt = 0;PortalEntry *be_newportal(void){	PortalEntry *entry;	char		buf[PortalNameLength];	/* ----------------	 *	generate a new name	 * ----------------	 */	if (be_portalcnt == 0)		be_portaloid = newoid();	be_portalcnt++;	snprintf(buf, PortalNameLength, "be_%u_%d", be_portaloid, be_portalcnt);	/* ----------------	 *	initialize the new portal entry and keep track	 *	of the current memory context for be_printtup().	 *	This is important - otherwise whatever we allocate	 *	will go away and the contents of the portal after	 *	PQexec() returns will be meaningless.	 * ----------------	 */	entry = pbuf_setup(buf);	entry->portalcxt = (Pointer) CurrentMemoryContext;	return entry;}/* ---------------- *		be_typeinit - initialize backend portal expected to hold *						query results. * *		used by BeginCommand() * ---------------- */voidbe_typeinit(PortalEntry *entry,			TupleDesc tupDesc,			int natts){	PortalBuffer *portal;	GroupBuffer *group;	int			i;	Form_pg_attribute *attrs = tupDesc->attrs;	/* ----------------	 *	add a new portal group to the portal	 * ----------------	 */	portal = entry->portal;	portal->no_groups++;	portal->groups = group = pbuf_addGroup(portal);	group->no_fields = natts;	/* ----------------	 *	initialize portal group type info	 * ----------------	 */	if (natts > 0)	{		group->types = pbuf_addTypes(natts);		for (i = 0; i < natts; ++i)		{			strncpy(group->types[i].name, attrs[i]->attname.data, NAMEDATALEN);			group->types[i].typid = attrs[i]->atttypid;			group->types[i].typlen = attrs[i]->attlen;		}	}}/* ---------------- *		be_printtup - add a tuple to a backend portal * *		used indirectly by ExecRetrieve() * *		This code is pretty much copied from printtup(), dump_type() *		and dump_data().  -cim 2/12/91 * ---------------- */voidbe_printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self){	int			i;	Datum		attr;	bool		isnull;	Oid			typoutput,				typelem;	PortalEntry *entry = NULL;	PortalBuffer *portal = NULL;	GroupBuffer *group = NULL;	TupleBlock *tuples = NULL;	char	  **values;	int		   *lengths;	MemoryContext savecxt;	/* ----------------	 *	get the current portal and group	 * ----------------	 */	entry = be_currentportal();	portal = entry->portal;	group = portal->groups;	/* ----------------	 *	switch to the portal's memory context so that	 *	the tuples we allocate are returned to the user.	 * ----------------	 */	savecxt = MemoryContextSwitchTo((MemoryContext) entry->portalcxt);	/* ----------------	 *	If no tuple block yet, allocate one.	 *	If the current block is full, allocate another one.	 * ----------------	 */	if (group->tuples == NULL)	{		tuples = group->tuples = pbuf_addTuples();		tuples->tuple_index = 0;	}	else	{		tuples = group->tuples;		/* walk to the end of the linked list of TupleBlocks */		while (tuples->next)			tuples = tuples->next;		/*		 * now, tuples is the last TupleBlock, check to see if it is full.		 * If so, allocate a new TupleBlock and add it to the end of the		 * chain		 */		if (tuples->tuple_index == TupleBlockSize)		{			tuples->next = pbuf_addTuples();			tuples = tuples->next;			tuples->tuple_index = 0;		}	}	/* ----------------	 *	Allocate space for a tuple.	 * ----------------	 */	tuples->values[tuples->tuple_index] = pbuf_addTuple(tuple->t_data->t_natts);	tuples->lengths[tuples->tuple_index] = pbuf_addTupleValueLengths(tuple->t_data->t_natts);	/* ----------------	 *	copy printable representations of the tuple's attributes	 *	to the portal.	 *	 *	This seems silly, because the user's function which is calling	 *	PQexec() or PQfn() will probably just convert this back into the	 *	internal form anyways, but the point here is to provide a uniform	 *	libpq interface and this is how the fe libpq interface currently	 *	works.	Pretty soon we'll have to add code to let the fe or be	 *	select the desired data representation and then deal with that.	 *	This should not be too hard, as there already exist typrecieve()	 *	and typsend() procedures for user-defined types (see pg_type.h)	 *	-cim 2/11/91	 * ----------------	 */	values = tuples->values[tuples->tuple_index];	lengths = tuples->lengths[tuples->tuple_index];	for (i = 0; i < tuple->t_data->t_natts; i++)	{		attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);		getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,						  &typoutput, &typelem);		lengths[i] = typeinfo->attrs[i]->attlen;		if (lengths[i] == -1)	/* variable length attribute */		{			if (!isnull)				lengths[i] = VARSIZE(attr) - VARHDRSZ;			else				lengths[i] = 0;		}		if (!isnull && OidIsValid(typoutput))			values[i] = fmgr(typoutput, attr, typelem,							 typeinfo->attrs[i]->atttypmod);		else			values[i] = NULL;	}	/* ----------------	 *	increment tuple group counters	 * ----------------	 */	portal->no_tuples++;	group->no_tuples++;	tuples->tuple_index++;	/* ----------------	 *	return to the original memory context	 * ----------------	 */	MemoryContextSwitchTo(savecxt);}

⌨️ 快捷键说明

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