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

📄 dest.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * dest.c *	  support for various communication destinations - see include/tcop/dest.h * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/tcop/dest.c,v 1.31 1999/05/25 22:42:06 momjian Exp $ * *------------------------------------------------------------------------- *//* *	 INTERFACE ROUTINES *		BeginCommand - prepare destination for tuples of the given type *		DestToFunction - identify per-tuple processing routines *		EndCommand - tell destination that no more tuples will arrive *		NullCommand - tell dest that an empty query string was recognized *		ReadyForQuery - tell dest that we are ready for a new query * *	 NOTES *		These routines do the appropriate work before and after *		tuples are returned by a query to keep the backend and the *		"destination" portals synchronized. * *		There is a second level of initialization/cleanup performed by the *		setup/cleanup routines identified by DestToFunction.  This could *		probably be merged with the work done by BeginCommand/EndCommand, *		but as of right now BeginCommand/EndCommand are used in a rather *		unstructured way --- some places call Begin without End, some vice *		versa --- so I think I'll just leave 'em alone for now.  tgl 1/99. * */#include <stdio.h>				/* for sprintf() */#include <string.h>#include "postgres.h"#include "access/htup.h"#include "libpq/libpq.h"#include "libpq/pqformat.h"#include "access/printtup.h"#include "utils/portal.h"#include "utils/palloc.h"#include "executor/executor.h"#include "tcop/dest.h"#include "catalog/pg_type.h"#include "utils/mcxt.h"#include "commands/async.h"static char CommandInfo[32] = {0};/* ---------------- *		dummy DestReceiver functions * ---------------- */static voiddonothingReceive(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self){}static voiddonothingSetup(DestReceiver *self, TupleDesc typeinfo){}static voiddonothingCleanup(DestReceiver *self){}/* ---------------- *		static DestReceiver structs for dest types needing no local state * ---------------- */static DestReceiver donothingDR = {	donothingReceive, donothingSetup, donothingCleanup};static DestReceiver printtup_internalDR = {	printtup_internal, donothingSetup, donothingCleanup};static DestReceiver be_printtupDR = {	be_printtup, donothingSetup, donothingCleanup};static DestReceiver debugtupDR = {	debugtup, donothingSetup, donothingCleanup};static DestReceiver spi_printtupDR = {	spi_printtup, donothingSetup, donothingCleanup};/* ---------------- *		BeginCommand - prepare destination for tuples of the given type * ---------------- */voidBeginCommand(char *pname,			 int operation,			 TupleDesc tupdesc,			 bool isIntoRel,			 bool isIntoPortal,			 char *tag,			 CommandDest dest){	PortalEntry *entry;	Form_pg_attribute *attrs = tupdesc->attrs;	int			natts = tupdesc->natts;	int			i;	char	   *p;	switch (dest)	{		case Remote:		case RemoteInternal:			/* ----------------			 *		if this is a "retrieve portal" query, done			 *		because nothing needs to be sent to the fe.			 * ----------------			 */			CommandInfo[0] = '\0';			if (isIntoPortal)				break;			/* ----------------			 *		if portal name not specified for remote query,			 *		use the "blank" portal.			 * ----------------			 */			if (pname == NULL)				pname = "blank";			/* ----------------			 *		send fe info on tuples we're about to send			 * ----------------			 */			pq_puttextmessage('P', pname);			/* ----------------			 *		if this is a retrieve, then we send back the tuple			 *		descriptor of the tuples.  "retrieve into" is an			 *		exception because no tuples are returned in that case.			 * ----------------			 */			if (operation == CMD_SELECT && !isIntoRel)			{				StringInfoData buf;				pq_beginmessage(&buf);				pq_sendbyte(&buf, 'T'); /* tuple descriptor message type */				pq_sendint(&buf, natts, 2);		/* # of attributes in												 * tuples */				for (i = 0; i < natts; ++i)				{					pq_sendstring(&buf, attrs[i]->attname.data);					pq_sendint(&buf, (int) attrs[i]->atttypid,							   sizeof(attrs[i]->atttypid));					pq_sendint(&buf, attrs[i]->attlen,							   sizeof(attrs[i]->attlen));					if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)						pq_sendint(&buf, attrs[i]->atttypmod,								   sizeof(attrs[i]->atttypmod));				}				pq_endmessage(&buf);			}			break;		case Local:			/* ----------------			 *		prepare local portal buffer for query results			 *		and setup result for PQexec()			 * ----------------			 */			entry = be_currentportal();			if (pname != NULL)				pbuf_setportalinfo(entry, pname);			if (operation == CMD_SELECT && !isIntoRel)			{				be_typeinit(entry, tupdesc, natts);				p = (char *) palloc(strlen(entry->name) + 2);				p[0] = 'P';				strcpy(p + 1, entry->name);			}			else			{				p = (char *) palloc(strlen(tag) + 2);				p[0] = 'C';				strcpy(p + 1, tag);			}			entry->result = p;			break;		case Debug:			/* ----------------			 *		show the return type of the tuples			 * ----------------			 */			if (pname == NULL)				pname = "blank";			showatts(pname, tupdesc);			break;		case None:		default:			break;	}}/* ---------------- *		DestToFunction - return appropriate receiver function set for dest * ---------------- */DestReceiver *DestToFunction(CommandDest dest){	switch (dest)	{			case Remote:			/* printtup wants a dynamically allocated DestReceiver */			return printtup_create_DR();			break;		case RemoteInternal:			return &printtup_internalDR;			break;		case Local:			return &be_printtupDR;			break;		case Debug:			return &debugtupDR;			break;		case SPI:			return &spi_printtupDR;			break;		case None:		default:			return &donothingDR;			break;	}	/*	 * never gets here, but DECstation lint appears to be stupid...	 */	return &donothingDR;}/* ---------------- *		EndCommand - tell destination that no more tuples will arrive * ---------------- */voidEndCommand(char *commandTag, CommandDest dest){	char		buf[64];	switch (dest)	{		case Remote:		case RemoteInternal:			/* ----------------			 *		tell the fe that the query is over			 * ----------------			 */			sprintf(buf, "%s%s", commandTag, CommandInfo);			pq_puttextmessage('C', buf);			CommandInfo[0] = '\0';			break;		case Local:		case Debug:		case None:		default:			break;	}}/* * These are necessary to sync communications between fe/be processes doing * COPY rel TO stdout * * or * * COPY rel FROM stdin * * NOTE: the message code letters are changed at protocol version 2.0 * to eliminate possible confusion with data tuple messages. */voidSendCopyBegin(void){	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)		pq_putbytes("H", 1);	/* new way */	else		pq_putbytes("B", 1);	/* old way */}voidReceiveCopyBegin(void){	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)		pq_putbytes("G", 1);	/* new way */	else		pq_putbytes("D", 1);	/* old way */	/* We *must* flush here to ensure FE knows it can send. */	pq_flush();}/* ---------------- *		NullCommand - tell dest that an empty query string was recognized * *		In FE/BE protocol version 1.0, this hack is necessary to support *		libpq's crufty way of determining whether a multiple-command *		query string is done.  In protocol 2.0 it's probably not really *		necessary to distinguish empty queries anymore, but we still do it *		for backwards compatibility with 1.0. * ---------------- */voidNullCommand(CommandDest dest){	switch (dest)	{			case RemoteInternal:			case Remote:			/* ----------------			 *		tell the fe that we saw an empty query string			 * ----------------			 */			pq_putbytes("I", 2);/* note we send I and \0 */			break;		case Local:		case Debug:		case None:		default:			break;	}}/* ---------------- *		ReadyForQuery - tell dest that we are ready for a new query * *		The ReadyForQuery message is sent in protocol versions 2.0 and up *		so that the FE can tell when we are done processing a query string. * *		Note that by flushing the stdio buffer here, we can avoid doing it *		most other places and thus reduce the number of separate packets sent. * ---------------- */voidReadyForQuery(CommandDest dest){	switch (dest)	{			case RemoteInternal:			case Remote:			if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)				pq_putbytes("Z", 1);			/* Flush output at end of cycle in any case. */			pq_flush();			break;		case Local:		case Debug:		case None:		default:			break;	}}voidUpdateCommandInfo(int operation, Oid lastoid, uint32 tuples){	switch (operation)	{			case CMD_INSERT:			if (tuples > 1)				lastoid = InvalidOid;			sprintf(CommandInfo, " %u %u", lastoid, tuples);			break;		case CMD_DELETE:		case CMD_UPDATE:			sprintf(CommandInfo, " %u", tuples);			break;		default:			CommandInfo[0] = '\0';			break;	}}

⌨️ 快捷键说明

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