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

📄 fe-protocol2.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
		else			conn->notifyHead = newNotify;		conn->notifyTail = newNotify;	}	return 0;}/* * PQgetCopyData - read a row of data from the backend during COPY OUT * * If successful, sets *buffer to point to a malloc'd row of data, and * returns row length (always > 0) as result. * Returns 0 if no row available yet (only possible if async is true), * -1 if end of copy (consult PQgetResult), or -2 if error (consult * PQerrorMessage). */intpqGetCopyData2(PGconn *conn, char **buffer, int async){	bool		found;	int			msgLength;	for (;;)	{		/*		 * Do we have a complete line of data?		 */		conn->inCursor = conn->inStart;		found = false;		while (conn->inCursor < conn->inEnd)		{			char		c = conn->inBuffer[conn->inCursor++];			if (c == '\n')			{				found = true;				break;			}		}		if (!found)			goto nodata;		msgLength = conn->inCursor - conn->inStart;		/*		 * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and		 * let caller read status with PQgetResult().		 */		if (msgLength == 3 &&			strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)		{			conn->inStart = conn->inCursor;			conn->asyncStatus = PGASYNC_BUSY;			return -1;		}		/*		 * Pass the line back to the caller.		 */		*buffer = (char *) malloc(msgLength + 1);		if (*buffer == NULL)		{			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("out of memory\n"));			return -2;		}		memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);		(*buffer)[msgLength] = '\0';	/* Add terminating null */		/* Mark message consumed */		conn->inStart = conn->inCursor;		return msgLength;nodata:		/* Don't block if async read requested */		if (async)			return 0;		/* Need to load more data */		if (pqWait(TRUE, FALSE, conn) ||			pqReadData(conn) < 0)			return -2;	}}/* * PQgetline - gets a newline-terminated string from the backend. * * See fe-exec.c for documentation. */intpqGetline2(PGconn *conn, char *s, int maxlen){	int			result = 1;		/* return value if buffer overflows */	if (conn->sock < 0)	{		*s = '\0';		return EOF;	}	/*	 * Since this is a purely synchronous routine, we don't bother to maintain	 * conn->inCursor; there is no need to back up.	 */	while (maxlen > 1)	{		if (conn->inStart < conn->inEnd)		{			char		c = conn->inBuffer[conn->inStart++];			if (c == '\n')			{				result = 0;		/* success exit */				break;			}			*s++ = c;			maxlen--;		}		else		{			/* need to load more data */			if (pqWait(TRUE, FALSE, conn) ||				pqReadData(conn) < 0)			{				result = EOF;				break;			}		}	}	*s = '\0';	return result;}/* * PQgetlineAsync - gets a COPY data row without blocking. * * See fe-exec.c for documentation. */intpqGetlineAsync2(PGconn *conn, char *buffer, int bufsize){	int			avail;	if (conn->asyncStatus != PGASYNC_COPY_OUT)		return -1;				/* we are not doing a copy... */	/*	 * Move data from libpq's buffer to the caller's. We want to accept data	 * only in units of whole lines, not partial lines.  This ensures that we	 * can recognize the terminator line "\\.\n".  (Otherwise, if it happened	 * to cross a packet/buffer boundary, we might hand the first one or two	 * characters off to the caller, which we shouldn't.)	 */	conn->inCursor = conn->inStart;	avail = bufsize;	while (avail > 0 && conn->inCursor < conn->inEnd)	{		char		c = conn->inBuffer[conn->inCursor++];		*buffer++ = c;		--avail;		if (c == '\n')		{			/* Got a complete line; mark the data removed from libpq */			conn->inStart = conn->inCursor;			/* Is it the endmarker line? */			if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')				return -1;			/* No, return the data line to the caller */			return bufsize - avail;		}	}	/*	 * We don't have a complete line. We'd prefer to leave it in libpq's	 * buffer until the rest arrives, but there is a special case: what if the	 * line is longer than the buffer the caller is offering us?  In that case	 * we'd better hand over a partial line, else we'd get into an infinite	 * loop. Do this in a way that ensures we can't misrecognize a terminator	 * line later: leave last 3 characters in libpq buffer.	 */	if (avail == 0 && bufsize > 3)	{		conn->inStart = conn->inCursor - 3;		return bufsize - 3;	}	return 0;}/* * PQendcopy * * See fe-exec.c for documentation. */intpqEndcopy2(PGconn *conn){	PGresult   *result;	if (conn->asyncStatus != PGASYNC_COPY_IN &&		conn->asyncStatus != PGASYNC_COPY_OUT)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("no COPY in progress\n"));		return 1;	}	/*	 * make sure no data is waiting to be sent, abort if we are non-blocking	 * and the flush fails	 */	if (pqFlush(conn) && pqIsnonblocking(conn))		return (1);	/* non blocking connections may have to abort at this point. */	if (pqIsnonblocking(conn) && PQisBusy(conn))		return (1);	/* Return to active duty */	conn->asyncStatus = PGASYNC_BUSY;	resetPQExpBuffer(&conn->errorMessage);	/* Wait for the completion response */	result = PQgetResult(conn);	/* Expecting a successful result */	if (result && result->resultStatus == PGRES_COMMAND_OK)	{		PQclear(result);		return 0;	}	/*	 * Trouble. For backwards-compatibility reasons, we issue the error	 * message as if it were a notice (would be nice to get rid of this	 * silliness, but too many apps probably don't handle errors from	 * PQendcopy reasonably).  Note that the app can still obtain the error	 * status from the PGconn object.	 */	if (conn->errorMessage.len > 0)	{		/* We have to strip the trailing newline ... pain in neck... */		char		svLast = conn->errorMessage.data[conn->errorMessage.len - 1];		if (svLast == '\n')			conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';		pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);		conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;	}	PQclear(result);	/*	 * The worst case is that we've lost sync with the backend entirely due to	 * application screwup of the copy in/out protocol. To recover, reset the	 * connection (talk about using a sledgehammer...)	 */	pqInternalNotice(&conn->noticeHooks,				   "lost synchronization with server, resetting connection");	/*	 * Users doing non-blocking connections need to handle the reset	 * themselves, they'll need to check the connection status if we return an	 * error.	 */	if (pqIsnonblocking(conn))		PQresetStart(conn);	else		PQreset(conn);	return 1;}/* * PQfn - Send a function call to the POSTGRES backend. * * See fe-exec.c for documentation. */PGresult *pqFunctionCall2(PGconn *conn, Oid fnid,				int *result_buf, int *actual_result_len,				int result_is_int,				const PQArgBlock *args, int nargs){	bool		needInput = false;	ExecStatusType status = PGRES_FATAL_ERROR;	char		id;	int			i;	/* PQfn already validated connection state */	if (pqPutMsgStart('F', false, conn) < 0 ||	/* function call msg */		pqPuts(" ", conn) < 0 ||	/* dummy string */		pqPutInt(fnid, 4, conn) != 0 || /* function id */		pqPutInt(nargs, 4, conn) != 0)	/* # of args */	{		pqHandleSendFailure(conn);		return NULL;	}	for (i = 0; i < nargs; ++i)	{							/* len.int4 + contents	   */		if (pqPutInt(args[i].len, 4, conn))		{			pqHandleSendFailure(conn);			return NULL;		}		if (args[i].isint)		{			if (pqPutInt(args[i].u.integer, 4, conn))			{				pqHandleSendFailure(conn);				return NULL;			}		}		else		{			if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))			{				pqHandleSendFailure(conn);				return NULL;			}		}	}	if (pqPutMsgEnd(conn) < 0 ||		pqFlush(conn))	{		pqHandleSendFailure(conn);		return NULL;	}	for (;;)	{		if (needInput)		{			/* Wait for some data to arrive (or for the channel to close) */			if (pqWait(TRUE, FALSE, conn) ||				pqReadData(conn) < 0)				break;		}		/*		 * Scan the message. If we run out of data, loop around to try again.		 */		conn->inCursor = conn->inStart;		needInput = true;		if (pqGetc(&id, conn))			continue;		/*		 * We should see V or E response to the command, but might get N		 * and/or A notices first. We also need to swallow the final Z before		 * returning.		 */		switch (id)		{			case 'V':			/* function result */				if (pqGetc(&id, conn))					continue;				if (id == 'G')				{					/* function returned nonempty value */					if (pqGetInt(actual_result_len, 4, conn))						continue;					if (result_is_int)					{						if (pqGetInt(result_buf, 4, conn))							continue;					}					else					{						if (pqGetnchar((char *) result_buf,									   *actual_result_len,									   conn))							continue;					}					if (pqGetc(&id, conn))		/* get the last '0' */						continue;				}				if (id == '0')				{					/* correctly finished function result message */					status = PGRES_COMMAND_OK;				}				else				{					/* The backend violates the protocol. */					printfPQExpBuffer(&conn->errorMessage,								  libpq_gettext("protocol error: id=0x%x\n"),									  id);					pqSaveErrorResult(conn);					conn->inStart = conn->inCursor;					return pqPrepareAsyncResult(conn);				}				break;			case 'E':			/* error return */				if (pqGetErrorNotice2(conn, true))					continue;				status = PGRES_FATAL_ERROR;				break;			case 'A':			/* notify message */				/* handle notify and go back to processing return values */				if (getNotify(conn))					continue;				break;			case 'N':			/* notice */				/* handle notice and go back to processing return values */				if (pqGetErrorNotice2(conn, false))					continue;				break;			case 'Z':			/* backend is ready for new query */				/* consume the message and exit */				conn->inStart = conn->inCursor;				/* if we saved a result object (probably an error), use it */				if (conn->result)					return pqPrepareAsyncResult(conn);				return PQmakeEmptyPGresult(conn, status);			default:				/* The backend violates the protocol. */				printfPQExpBuffer(&conn->errorMessage,								  libpq_gettext("protocol error: id=0x%x\n"),								  id);				pqSaveErrorResult(conn);				conn->inStart = conn->inCursor;				return pqPrepareAsyncResult(conn);		}		/* Completed this message, keep going */		conn->inStart = conn->inCursor;		needInput = false;	}	/*	 * We fall out of the loop only upon failing to read data.	 * conn->errorMessage has been set by pqWait or pqReadData. We want to	 * append it to any already-received error message.	 */	pqSaveErrorResult(conn);	return pqPrepareAsyncResult(conn);}/* * Construct startup packet * * Returns a malloc'd packet buffer, or NULL if out of memory */char *pqBuildStartupPacket2(PGconn *conn, int *packetlen,					  const PQEnvironmentOption *options){	StartupPacket *startpacket;	*packetlen = sizeof(StartupPacket);	startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));	if (!startpacket)		return NULL;	MemSet(startpacket, 0, sizeof(StartupPacket));	startpacket->protoVersion = htonl(conn->pversion);	strncpy(startpacket->user, conn->pguser, SM_USER);	strncpy(startpacket->database, conn->dbName, SM_DATABASE);	strncpy(startpacket->tty, conn->pgtty, SM_TTY);	if (conn->pgoptions)		strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);	return (char *) startpacket;}

⌨️ 快捷键说明

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