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

📄 printtup.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * printtup.c *	  Routines to print out tuples to the destination (both frontend *	  clients and standalone backends are supported here). * * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.78 2003/08/06 17:46:45 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "access/printtup.h"#include "libpq/libpq.h"#include "libpq/pqformat.h"#include "utils/lsyscache.h"#include "utils/portal.h"static void printtup_startup(DestReceiver *self, int operation,				 TupleDesc typeinfo);static void printtup(HeapTuple tuple, TupleDesc typeinfo,		 DestReceiver *self);static void printtup_20(HeapTuple tuple, TupleDesc typeinfo,			DestReceiver *self);static void printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo,					 DestReceiver *self);static void printtup_shutdown(DestReceiver *self);static void printtup_destroy(DestReceiver *self);/* ---------------------------------------------------------------- *		printtup / debugtup support * ---------------------------------------------------------------- *//* ---------------- *		Private state for a printtup destination object * * NOTE: finfo is the lookup info for either typoutput or typsend, whichever * we are using for this column. * ---------------- */typedef struct{								/* Per-attribute information */	Oid			typoutput;		/* Oid for the type's text output fn */	Oid			typsend;		/* Oid for the type's binary output fn */	Oid			typelem;		/* typelem value to pass to the output fn */	bool		typisvarlena;	/* is it varlena (ie possibly toastable)? */	int16		format;			/* format code for this column */	FmgrInfo	finfo;			/* Precomputed call info for output fn */} PrinttupAttrInfo;typedef struct{	DestReceiver pub;			/* publicly-known function pointers */	Portal		portal;			/* the Portal we are printing from */	bool		sendDescrip;	/* send RowDescription at startup? */	TupleDesc	attrinfo;		/* The attr info we are set up for */	int			nattrs;	PrinttupAttrInfo *myinfo;	/* Cached info about each attr */} DR_printtup;/* ---------------- *		Initialize: create a DestReceiver for printtup * ---------------- */DestReceiver *printtup_create_DR(CommandDest dest, Portal portal){	DR_printtup *self = (DR_printtup *) palloc(sizeof(DR_printtup));	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)		self->pub.receiveTuple = printtup;	else	{		/*		 * In protocol 2.0 the Bind message does not exist, so there is no		 * way for the columns to have different print formats; it's		 * sufficient to look at the first one.		 */		if (portal->formats && portal->formats[0] != 0)			self->pub.receiveTuple = printtup_internal_20;		else			self->pub.receiveTuple = printtup_20;	}	self->pub.rStartup = printtup_startup;	self->pub.rShutdown = printtup_shutdown;	self->pub.rDestroy = printtup_destroy;	self->pub.mydest = dest;	self->portal = portal;	/* Send T message automatically if Remote, but not if RemoteExecute */	self->sendDescrip = (dest == Remote);	self->attrinfo = NULL;	self->nattrs = 0;	self->myinfo = NULL;	return (DestReceiver *) self;}static voidprinttup_startup(DestReceiver *self, int operation, TupleDesc typeinfo){	DR_printtup *myState = (DR_printtup *) self;	Portal		portal = myState->portal;	if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)	{		/*		 * Send portal name to frontend (obsolete cruft, gone in proto		 * 3.0)		 *		 * If portal name not specified, use "blank" portal.		 */		const char *portalName = portal->name;		if (portalName == NULL || portalName[0] == '\0')			portalName = "blank";		pq_puttextmessage('P', portalName);	}	/*	 * If this is a retrieve, and we are supposed to emit row	 * descriptions, then we send back the tuple descriptor of the tuples.	 */	if (operation == CMD_SELECT && myState->sendDescrip)	{		List	   *targetlist;		if (portal->strategy == PORTAL_ONE_SELECT)			targetlist = ((Query *) lfirst(portal->parseTrees))->targetList;		else			targetlist = NIL;		SendRowDescriptionMessage(typeinfo, targetlist, portal->formats);	}	/* ----------------	 * We could set up the derived attr info at this time, but we postpone it	 * until the first call of printtup, for 2 reasons:	 * 1. We don't waste time (compared to the old way) if there are no	 *	  tuples at all to output.	 * 2. Checking in printtup allows us to handle the case that the tuples	 *	  change type midway through (although this probably can't happen in	 *	  the current executor).	 * ----------------	 */}/* * SendRowDescriptionMessage --- send a RowDescription message to the frontend * * Notes: the TupleDesc has typically been manufactured by ExecTypeFromTL() * or some similar function; it does not contain a full set of fields. * The targetlist will be NIL when executing a utility function that does * not have a plan.  If the targetlist isn't NIL then it is a Query node's * targetlist; it is up to us to ignore resjunk columns in it.	The formats[] * array pointer might be NULL (if we are doing Describe on a prepared stmt); * send zeroes for the format codes in that case. */voidSendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats){	Form_pg_attribute *attrs = typeinfo->attrs;	int			natts = typeinfo->natts;	int			proto = PG_PROTOCOL_MAJOR(FrontendProtocol);	int			i;	StringInfoData buf;	pq_beginmessage(&buf, 'T'); /* tuple descriptor message type */	pq_sendint(&buf, natts, 2); /* # of attrs in tuples */	for (i = 0; i < natts; ++i)	{		Oid			atttypid = attrs[i]->atttypid;		int32		atttypmod = attrs[i]->atttypmod;		Oid			basetype;		pq_sendstring(&buf, NameStr(attrs[i]->attname));		/* column ID info appears in protocol 3.0 and up */		if (proto >= 3)		{			/* Do we have a non-resjunk tlist item? */			while (targetlist &&				   ((TargetEntry *) lfirst(targetlist))->resdom->resjunk)				targetlist = lnext(targetlist);			if (targetlist)			{				Resdom	   *res = ((TargetEntry *) lfirst(targetlist))->resdom;				pq_sendint(&buf, res->resorigtbl, 4);				pq_sendint(&buf, res->resorigcol, 2);				targetlist = lnext(targetlist);			}			else			{				/* No info available, so send zeroes */				pq_sendint(&buf, 0, 4);				pq_sendint(&buf, 0, 2);			}		}		/* If column is a domain, send the base type and typmod instead */		basetype = getBaseType(atttypid);		if (basetype != atttypid)		{			atttypmod = get_typtypmod(atttypid);			atttypid = basetype;		}		pq_sendint(&buf, (int) atttypid, sizeof(atttypid));		pq_sendint(&buf, attrs[i]->attlen, sizeof(attrs[i]->attlen));		/* typmod appears in protocol 2.0 and up */		if (proto >= 2)			pq_sendint(&buf, atttypmod, sizeof(atttypmod));		/* format info appears in protocol 3.0 and up */		if (proto >= 3)		{			if (formats)				pq_sendint(&buf, formats[i], 2);			else				pq_sendint(&buf, 0, 2);		}	}	pq_endmessage(&buf);}/* * Get the lookup info that printtup() needs */static voidprinttup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs){	int16	   *formats = myState->portal->formats;	int			i;	if (myState->myinfo)		pfree(myState->myinfo); /* get rid of any old data */	myState->myinfo = NULL;	myState->attrinfo = typeinfo;	myState->nattrs = numAttrs;	if (numAttrs <= 0)		return;	myState->myinfo = (PrinttupAttrInfo *)		palloc0(numAttrs * sizeof(PrinttupAttrInfo));	for (i = 0; i < numAttrs; i++)	{		PrinttupAttrInfo *thisState = myState->myinfo + i;		int16		format = (formats ? formats[i] : 0);		thisState->format = format;		if (format == 0)		{			getTypeOutputInfo(typeinfo->attrs[i]->atttypid,							  &thisState->typoutput,							  &thisState->typelem,							  &thisState->typisvarlena);			fmgr_info(thisState->typoutput, &thisState->finfo);		}		else if (format == 1)		{			getTypeBinaryOutputInfo(typeinfo->attrs[i]->atttypid,									&thisState->typsend,									&thisState->typelem,									&thisState->typisvarlena);			fmgr_info(thisState->typsend, &thisState->finfo);		}		else			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("unsupported format code: %d", format)));	}}/* ---------------- *		printtup --- print a tuple in protocol 3.0 * ---------------- */static voidprinttup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self){	DR_printtup *myState = (DR_printtup *) self;	StringInfoData buf;	int			natts = typeinfo->natts;	int			i;	/* Set or update my derived attribute info, if needed */	if (myState->attrinfo != typeinfo || myState->nattrs != natts)		printtup_prepare_info(myState, typeinfo, natts);	/*	 * Prepare a DataRow message	 */	pq_beginmessage(&buf, 'D');	pq_sendint(&buf, natts, 2);	/*	 * send the attributes of this tuple	 */	for (i = 0; i < natts; ++i)	{		PrinttupAttrInfo *thisState = myState->myinfo + i;		Datum		origattr,					attr;		bool		isnull;		origattr = heap_getattr(tuple, i + 1, typeinfo, &isnull);		if (isnull)		{			pq_sendint(&buf, -1, 4);			continue;		}		/*		 * If we have a toasted datum, forcibly detoast it here to avoid		 * memory leakage inside the type's output routine.		 */		if (thisState->typisvarlena)			attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));

⌨️ 快捷键说明

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