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

📄 fe-exec.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 */	while (pqReadData(conn) > 0)		 /* loop until no more data readable */ ;	/*	 * Parse any available input messages.	Since we are in PGASYNC_IDLE	 * state, only NOTICE and NOTIFY messages will be eaten.	 */	parseInput(conn);}/* * Consume any available input from the backend * 0 return: some kind of trouble * 1 return: no problem */intPQconsumeInput(PGconn *conn){	if (!conn)		return 0;	/*	 * for non-blocking connections try to flush the send-queue, otherwise we	 * may never get a response for something that may not have already been	 * sent because it's in our write buffer!	 */	if (pqIsnonblocking(conn))	{		if (pqFlush(conn) < 0)			return 0;	}	/*	 * Load more data, if available. We do this no matter what state we are	 * in, since we are probably getting called because the application wants	 * to get rid of a read-select condition. Note that we will NOT block	 * waiting for more input.	 */	if (pqReadData(conn) < 0)		return 0;	/* Parsing of the data waits till later. */	return 1;}/* * parseInput: if appropriate, parse input data from backend * until input is exhausted or a stopping state is reached. * Note that this function will NOT attempt to read more data from the backend. */static voidparseInput(PGconn *conn){	if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)		pqParseInput3(conn);	else		pqParseInput2(conn);}/* * PQisBusy *	 Return TRUE if PQgetResult would block waiting for input. */intPQisBusy(PGconn *conn){	if (!conn)		return FALSE;	/* Parse any available data, if our state permits. */	parseInput(conn);	/* PQgetResult will return immediately in all states except BUSY. */	return conn->asyncStatus == PGASYNC_BUSY;}/* * PQgetResult *	  Get the next PGresult produced by a query.  Returns NULL if no *	  query work remains or an error has occurred (e.g. out of *	  memory). */PGresult *PQgetResult(PGconn *conn){	PGresult   *res;	if (!conn)		return NULL;	/* Parse any available data, if our state permits. */	parseInput(conn);	/* If not ready to return something, block until we are. */	while (conn->asyncStatus == PGASYNC_BUSY)	{		int			flushResult;		/*		 * If data remains unsent, send it.  Else we might be waiting for the		 * result of a command the backend hasn't even got yet.		 */		while ((flushResult = pqFlush(conn)) > 0)		{			if (pqWait(FALSE, TRUE, conn))			{				flushResult = -1;				break;			}		}		/* Wait for some more data, and load it. */		if (flushResult ||			pqWait(TRUE, FALSE, conn) ||			pqReadData(conn) < 0)		{			/*			 * conn->errorMessage has been set by pqWait or pqReadData. We			 * want to append it to any already-received error message.			 */			pqSaveErrorResult(conn);			conn->asyncStatus = PGASYNC_IDLE;			return pqPrepareAsyncResult(conn);		}		/* Parse it. */		parseInput(conn);	}	/* Return the appropriate thing. */	switch (conn->asyncStatus)	{		case PGASYNC_IDLE:			res = NULL;			/* query is complete */			break;		case PGASYNC_READY:			res = pqPrepareAsyncResult(conn);			/* Set the state back to BUSY, allowing parsing to proceed. */			conn->asyncStatus = PGASYNC_BUSY;			break;		case PGASYNC_COPY_IN:			if (conn->result && conn->result->resultStatus == PGRES_COPY_IN)				res = pqPrepareAsyncResult(conn);			else				res = PQmakeEmptyPGresult(conn, PGRES_COPY_IN);			break;		case PGASYNC_COPY_OUT:			if (conn->result && conn->result->resultStatus == PGRES_COPY_OUT)				res = pqPrepareAsyncResult(conn);			else				res = PQmakeEmptyPGresult(conn, PGRES_COPY_OUT);			break;		default:			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("unexpected asyncStatus: %d\n"),							  (int) conn->asyncStatus);			res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);			break;	}	return res;}/* * PQexec *	  send a query to the backend and package up the result in a PGresult * * If the query was not even sent, return NULL; conn->errorMessage is set to * a relevant message. * If the query was sent, a new PGresult is returned (which could indicate * either success or failure). * The user is responsible for freeing the PGresult via PQclear() * when done with it. */PGresult *PQexec(PGconn *conn, const char *query){	if (!PQexecStart(conn))		return NULL;	if (!PQsendQuery(conn, query))		return NULL;	return PQexecFinish(conn);}/* * PQexecParams *		Like PQexec, but use protocol 3.0 so we can pass parameters */PGresult *PQexecParams(PGconn *conn,			 const char *command,			 int nParams,			 const Oid *paramTypes,			 const char *const * paramValues,			 const int *paramLengths,			 const int *paramFormats,			 int resultFormat){	if (!PQexecStart(conn))		return NULL;	if (!PQsendQueryParams(conn, command,						   nParams, paramTypes, paramValues, paramLengths,						   paramFormats, resultFormat))		return NULL;	return PQexecFinish(conn);}/* * PQprepare *	  Creates a prepared statement by issuing a v3.0 parse message. * * If the query was not even sent, return NULL; conn->errorMessage is set to * a relevant message. * If the query was sent, a new PGresult is returned (which could indicate * either success or failure). * The user is responsible for freeing the PGresult via PQclear() * when done with it. */PGresult *PQprepare(PGconn *conn,		  const char *stmtName, const char *query,		  int nParams, const Oid *paramTypes){	if (!PQexecStart(conn))		return NULL;	if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))		return NULL;	return PQexecFinish(conn);}/* * PQexecPrepared *		Like PQexec, but execute a previously prepared statement, *		using protocol 3.0 so we can pass parameters */PGresult *PQexecPrepared(PGconn *conn,			   const char *stmtName,			   int nParams,			   const char *const * paramValues,			   const int *paramLengths,			   const int *paramFormats,			   int resultFormat){	if (!PQexecStart(conn))		return NULL;	if (!PQsendQueryPrepared(conn, stmtName,							 nParams, paramValues, paramLengths,							 paramFormats, resultFormat))		return NULL;	return PQexecFinish(conn);}/* * Common code for PQexec and sibling routines: prepare to send command */static boolPQexecStart(PGconn *conn){	PGresult   *result;	if (!conn)		return false;	/*	 * Silently discard any prior query result that application didn't eat.	 * This is probably poor design, but it's here for backward compatibility.	 */	while ((result = PQgetResult(conn)) != NULL)	{		ExecStatusType resultStatus = result->resultStatus;		PQclear(result);		/* only need its status */		if (resultStatus == PGRES_COPY_IN)		{			if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)			{				/* In protocol 3, we can get out of a COPY IN state */				if (PQputCopyEnd(conn,						 libpq_gettext("COPY terminated by new PQexec")) < 0)					return false;				/* keep waiting to swallow the copy's failure message */			}			else			{				/* In older protocols we have to punt */				printfPQExpBuffer(&conn->errorMessage,				  libpq_gettext("COPY IN state must be terminated first\n"));				return false;			}		}		else if (resultStatus == PGRES_COPY_OUT)		{			if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)			{				/*				 * In protocol 3, we can get out of a COPY OUT state: we just				 * switch back to BUSY and allow the remaining COPY data to be				 * dropped on the floor.				 */				conn->asyncStatus = PGASYNC_BUSY;				/* keep waiting to swallow the copy's completion message */			}			else			{				/* In older protocols we have to punt */				printfPQExpBuffer(&conn->errorMessage,				 libpq_gettext("COPY OUT state must be terminated first\n"));				return false;			}		}		/* check for loss of connection, too */		if (conn->status == CONNECTION_BAD)			return false;	}	/* OK to send a command */	return true;}/* * Common code for PQexec and sibling routines: wait for command result */static PGresult *PQexecFinish(PGconn *conn){	PGresult   *result;	PGresult   *lastResult;	/*	 * For backwards compatibility, return the last result if there are more	 * than one --- but merge error messages if we get more than one error	 * result.	 *	 * We have to stop if we see copy in/out, however. We will resume parsing	 * after application performs the data transfer.	 *	 * Also stop if the connection is lost (else we'll loop infinitely).	 */	lastResult = NULL;	while ((result = PQgetResult(conn)) != NULL)	{		if (lastResult)		{			if (lastResult->resultStatus == PGRES_FATAL_ERROR &&				result->resultStatus == PGRES_FATAL_ERROR)			{				pqCatenateResultError(lastResult, result->errMsg);				PQclear(result);				result = lastResult;				/*				 * Make sure PQerrorMessage agrees with concatenated result				 */				resetPQExpBuffer(&conn->errorMessage);				appendPQExpBufferStr(&conn->errorMessage, result->errMsg);			}			else				PQclear(lastResult);		}		lastResult = result;		if (result->resultStatus == PGRES_COPY_IN ||			result->resultStatus == PGRES_COPY_OUT ||			conn->status == CONNECTION_BAD)			break;	}	return lastResult;}/* * PQnotifies *	  returns a PGnotify* structure of the latest async notification * that has not yet been handled * * returns NULL, if there is currently * no unhandled async notification from the backend * * the CALLER is responsible for FREE'ing the structure returned */PGnotify *PQnotifies(PGconn *conn){	PGnotify   *event;	if (!conn)		return NULL;	/* Parse any available data to see if we can extract NOTIFY messages. */	parseInput(conn);	event = conn->notifyHead;	if (event)	{		conn->notifyHead = event->next;		if (!conn->notifyHead)			conn->notifyTail = NULL;		event->next = NULL;		/* don't let app see the internal state */	}	return event;}/* * PQputCopyData - send some data to the backend during COPY IN * * Returns 1 if successful, 0 if data could not be sent (only possible * in nonblock mode), or -1 if an error occurs. */intPQputCopyData(PGconn *conn, const char *buffer, int nbytes){	if (!conn)		return -1;	if (conn->asyncStatus != PGASYNC_COPY_IN)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("no COPY in progress\n"));		return -1;	}	/*	 * Process any NOTICE or NOTIFY messages that might be pending in the	 * input buffer.  Since the server might generate many notices during	 * the COPY, we want to clean those out reasonably promptly to prevent	 * indefinite expansion of the input buffer.  (Note: the actual read	 * of input data into the input buffer happens down inside pqSendSome,	 * but it's not authorized to get rid of the data again.)	 */	parseInput(conn);	if (nbytes > 0)	{		/*		 * Try to flush any previously sent data in preference to growing the		 * output buffer.  If we can't enlarge the buffer enough to hold the		 * data, return 0 in the nonblock case, else hard error. (For		 * simplicity, always assume 5 bytes of overhead even in protocol 2.0		 * case.)		 */		if ((conn->outBufSize - conn->outCount - 5) < nbytes)		{			if (pqFlush(conn) < 0)				return -1;			if (pqCheckOutBufferSpace(conn->outCount + 5 + nbytes, conn))				return pqIsnonblocking(conn) ? 0 : -1;		}		/* Send the data (too simple to delegate to fe-protocol files) */		if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)		{			if (pqPutMsgStart('d', false, conn) < 0 ||				pqPutnchar(buffer, nbytes, conn) < 0 ||				pqPutMsgEnd(conn) < 0)				return -1;		}		else		{			if (pqPutMsgStart(0, false, conn) < 0 ||				pqPutnchar(buffer, nbytes, conn) < 0 ||				pqPutMsgEnd(conn) < 0)				return -1;		}	}	return 1;}/* * PQputCopyEnd - send EOF indication to the backend during COPY IN * * After calling this, use PQgetResult() to check command completion status. * * Returns 1 if successful, 0 if data could not be sent (only possible * in nonblock mode), or -1 if an error occurs. */intPQputCopyEnd(PGconn *conn, const char *errormsg){	if (!conn)		return -1;	if (conn->asyncStatus != PGASYNC_COPY_IN)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("no COPY in progress\n"));		return -1;	}	/*	 * Send the COPY END indicator.  This is simple enough that we don't	 * bother delegating it to the fe-protocol files.	 */	if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)	{		if (errormsg)		{			/* Send COPY FAIL */			if (pqPutMsgStart('f', false, conn) < 0 ||				pqPuts(errormsg, conn) < 0 ||				pqPutMsgEnd(conn) < 0)				return -1;		}		else		{			/* Send COPY DONE */			if (pqPutMsgStart('c', false, conn) < 0 ||				pqPutMsgEnd(conn) < 0)				return -1;		}		/*		 * If we sent the COPY command in extended-query mode, we must issue a		 * Sync as well.		 */		if (conn->queryclass != PGQUERY_SIMPLE)		{			if (pqPutMsgStart('S', false, conn) < 0 ||				pqPutMsgEnd(conn) < 0)				return -1;		}	}	else	{		if (errormsg)		{			/* Ooops, no way to do this in 2.0 */			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("function requires at least protocol version 3.0\n"));			return -1;		}		else

⌨️ 快捷键说明

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