diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 2328d8f..80f7014 100644
*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
*************** char *PQresultErrorMessage(const PGresul
*** 2691,2696 ****
--- 2691,2738 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="libpq-pqresultverboseerrormessage">
+       <term>
+        <function>PQresultVerboseErrorMessage</function>
+        <indexterm>
+         <primary>PQresultVerboseErrorMessage</primary>
+        </indexterm>
+       </term>
+ 
+       <listitem>
+        <para>
+         Returns a reformatted version of the error message associated with
+         a <structname>PGresult</> object.
+ <synopsis>
+ char *PQresultVerboseErrorMessage(const PGresult *res,
+                                   PGVerbosity verbosity,
+                                   PGContextVisibility show_context);
+ </synopsis>
+         In some situations a client might wish to obtain a more detailed
+         version of a previously-reported error.
+         <function>PQresultVerboseErrorMessage</function> addresses this need
+         by computing the message that would have been produced
+         by <function>PQresultErrorMessage</function> if the specified
+         verbosity settings had been in effect for the connection when the
+         given <structname>PGresult</> was generated.  If
+         the <structname>PGresult</> is not an error result,
+         <quote>PGresult is not an error result</> is reported instead.
+         The returned string includes a trailing newline.
+        </para>
+ 
+        <para>
+         Unlike most other functions for extracting data from
+         a <structname>PGresult</>, the result of this function is a freshly
+         allocated string.  The caller must free it
+         using <function>PQfreemem()</> when the string is no longer needed.
+        </para>
+ 
+        <para>
+         A NULL return is possible if there is insufficient memory.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       <varlistentry id="libpq-pqresulterrorfield">
        <term><function>PQresultErrorField</function><indexterm><primary>PQresultErrorField</></></term>
        <listitem>
*************** PGVerbosity PQsetErrorVerbosity(PGconn *
*** 5582,5587 ****
--- 5624,5631 ----
        mode includes all available fields.  Changing the verbosity does not
        affect the messages available from already-existing
        <structname>PGresult</> objects, only subsequently-created ones.
+       (But see <function>PQresultVerboseErrorMessage</function> if you
+       want to print a previous error with a different verbosity.)
       </para>
      </listitem>
     </varlistentry>
*************** PGContextVisibility PQsetErrorContextVis
*** 5622,5627 ****
--- 5666,5673 ----
        affect the messages available from
        already-existing <structname>PGresult</> objects, only
        subsequently-created ones.
+       (But see <function>PQresultVerboseErrorMessage</function> if you
+       want to print a previous error with a different display mode.)
       </para>
      </listitem>
     </varlistentry>
*************** PQsetNoticeProcessor(PGconn *conn,
*** 6089,6096 ****
     receiver function is called.  It is passed the message in the form of
     a <symbol>PGRES_NONFATAL_ERROR</symbol>
     <structname>PGresult</structname>.  (This allows the receiver to extract
!    individual fields using <function>PQresultErrorField</>, or the complete
!    preformatted message using <function>PQresultErrorMessage</>.) The same
     void pointer passed to <function>PQsetNoticeReceiver</function> is also
     passed.  (This pointer can be used to access application-specific state
     if needed.)
--- 6135,6143 ----
     receiver function is called.  It is passed the message in the form of
     a <symbol>PGRES_NONFATAL_ERROR</symbol>
     <structname>PGresult</structname>.  (This allows the receiver to extract
!    individual fields using <function>PQresultErrorField</>, or complete
!    preformatted messages using <function>PQresultErrorMessage</> or
!    <function>PQresultVerboseErrorMessage</>.) The same
     void pointer passed to <function>PQsetNoticeReceiver</function> is also
     passed.  (This pointer can be used to access application-specific state
     if needed.)
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index c69a4d5..21dd772 100644
*** a/src/interfaces/libpq/exports.txt
--- b/src/interfaces/libpq/exports.txt
*************** PQsslStruct               167
*** 170,172 ****
--- 170,173 ----
  PQsslAttributeNames       168
  PQsslAttribute            169
  PQsetErrorContextVisibility 170
+ PQresultVerboseErrorMessage 171
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 41937c0..2621767 100644
*** a/src/interfaces/libpq/fe-exec.c
--- b/src/interfaces/libpq/fe-exec.c
*************** PQmakeEmptyPGresult(PGconn *conn, ExecSt
*** 159,164 ****
--- 159,165 ----
  	result->nEvents = 0;
  	result->errMsg = NULL;
  	result->errFields = NULL;
+ 	result->errQuery = NULL;
  	result->null_field[0] = '\0';
  	result->curBlock = NULL;
  	result->curOffset = 0;
*************** PQresultErrorMessage(const PGresult *res
*** 2599,2604 ****
--- 2600,2643 ----
  }
  
  char *
+ PQresultVerboseErrorMessage(const PGresult *res,
+ 							PGVerbosity verbosity,
+ 							PGContextVisibility show_context)
+ {
+ 	PQExpBufferData workBuf;
+ 
+ 	/*
+ 	 * Because the caller is expected to free the result string, we must
+ 	 * strdup any constant result.  We use plain strdup and document that
+ 	 * callers should expect NULL if out-of-memory.
+ 	 */
+ 	if (!res ||
+ 		(res->resultStatus != PGRES_FATAL_ERROR &&
+ 		 res->resultStatus != PGRES_NONFATAL_ERROR))
+ 		return strdup(libpq_gettext("PGresult is not an error result\n"));
+ 
+ 	initPQExpBuffer(&workBuf);
+ 
+ 	/*
+ 	 * Currently, we pass this off to fe-protocol3.c in all cases; it will
+ 	 * behave reasonably sanely with an error reported by fe-protocol2.c as
+ 	 * well.  If necessary, we could record the protocol version in PGresults
+ 	 * so as to be able to invoke a version-specific message formatter, but
+ 	 * for now there's no need.
+ 	 */
+ 	pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
+ 
+ 	/* If insufficient memory to format the message, fail cleanly */
+ 	if (PQExpBufferDataBroken(workBuf))
+ 	{
+ 		termPQExpBuffer(&workBuf);
+ 		return strdup(libpq_gettext("out of memory\n"));
+ 	}
+ 
+ 	return workBuf.data;
+ }
+ 
+ char *
  PQresultErrorField(const PGresult *res, int fieldcode)
  {
  	PGMessageField *pfield;
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 3034773..481ee9b 100644
*** a/src/interfaces/libpq/fe-protocol3.c
--- b/src/interfaces/libpq/fe-protocol3.c
*************** pqGetErrorNotice3(PGconn *conn, bool isE
*** 878,886 ****
  	PGresult   *res = NULL;
  	PQExpBufferData workBuf;
  	char		id;
- 	const char *val;
- 	const char *querytext = NULL;
- 	int			querypos = 0;
  
  	/*
  	 * Since the fields might be pretty long, we create a temporary
--- 878,883 ----
*************** pqGetErrorNotice3(PGconn *conn, bool isE
*** 905,910 ****
--- 902,909 ----
  
  	/*
  	 * Read the fields and save into res.
+ 	 *
+ 	 * Also, save the SQLSTATE in conn->last_sqlstate.
  	 */
  	for (;;)
  	{
*************** pqGetErrorNotice3(PGconn *conn, bool isE
*** 915,956 ****
  		if (pqGets(&workBuf, conn))
  			goto fail;
  		pqSaveMessageField(res, id, workBuf.data);
  	}
  
  	/*
  	 * Now build the "overall" error message for PQresultErrorMessage.
- 	 *
- 	 * Also, save the SQLSTATE in conn->last_sqlstate.
  	 */
  	resetPQExpBuffer(&workBuf);
  	val = PQresultErrorField(res, PG_DIAG_SEVERITY);
  	if (val)
! 		appendPQExpBuffer(&workBuf, "%s:  ", val);
! 	val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
! 	if (val)
  	{
! 		if (strlen(val) < sizeof(conn->last_sqlstate))
! 			strcpy(conn->last_sqlstate, val);
! 		if (conn->verbosity == PQERRORS_VERBOSE)
! 			appendPQExpBuffer(&workBuf, "%s: ", val);
  	}
  	val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
  	if (val)
! 		appendPQExpBufferStr(&workBuf, val);
  	val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
  	if (val)
  	{
! 		if (conn->verbosity != PQERRORS_TERSE && conn->last_query != NULL)
  		{
  			/* emit position as a syntax cursor display */
! 			querytext = conn->last_query;
  			querypos = atoi(val);
  		}
  		else
  		{
  			/* emit position as text addition to primary message */
  			/* translator: %s represents a digit string */
! 			appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
  							  val);
  		}
  	}
--- 914,1032 ----
  		if (pqGets(&workBuf, conn))
  			goto fail;
  		pqSaveMessageField(res, id, workBuf.data);
+ 		if (id == PG_DIAG_SQLSTATE)
+ 			strlcpy(conn->last_sqlstate, workBuf.data,
+ 					sizeof(conn->last_sqlstate));
  	}
  
  	/*
+ 	 * Save the active query text, if any, into res as well.
+ 	 */
+ 	if (res && conn->last_query)
+ 		res->errQuery = pqResultStrdup(res, conn->last_query);
+ 
+ 	/*
  	 * Now build the "overall" error message for PQresultErrorMessage.
  	 */
  	resetPQExpBuffer(&workBuf);
+ 	pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
+ 
+ 	/*
+ 	 * Either save error as current async result, or just emit the notice.
+ 	 */
+ 	if (isError)
+ 	{
+ 		if (res)
+ 			res->errMsg = pqResultStrdup(res, workBuf.data);
+ 		pqClearAsyncResult(conn);
+ 		conn->result = res;
+ 		if (PQExpBufferDataBroken(workBuf))
+ 			printfPQExpBuffer(&conn->errorMessage,
+ 							  libpq_gettext("out of memory"));
+ 		else
+ 			appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
+ 	}
+ 	else
+ 	{
+ 		/* if we couldn't allocate the result set, just discard the NOTICE */
+ 		if (res)
+ 		{
+ 			/* We can cheat a little here and not copy the message. */
+ 			res->errMsg = workBuf.data;
+ 			if (res->noticeHooks.noticeRec != NULL)
+ 				(*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
+ 			PQclear(res);
+ 		}
+ 	}
+ 
+ 	termPQExpBuffer(&workBuf);
+ 	return 0;
+ 
+ fail:
+ 	PQclear(res);
+ 	termPQExpBuffer(&workBuf);
+ 	return EOF;
+ }
+ 
+ /*
+  * Construct an error message from the fields in the given PGresult,
+  * appending it to the contents of "msg".
+  */
+ void
+ pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
+ 					 PGVerbosity verbosity, PGContextVisibility show_context)
+ {
+ 	const char *val;
+ 	const char *querytext = NULL;
+ 	int			querypos = 0;
+ 
+ 	/* If we couldn't allocate a PGresult, just say "out of memory" */
+ 	if (res == NULL)
+ 	{
+ 		appendPQExpBuffer(msg, libpq_gettext("out of memory\n"));
+ 		return;
+ 	}
+ 
+ 	/*
+ 	 * If we don't have any broken-down fields, just return the base message.
+ 	 * This mainly applies if we're given a libpq-generated error result.
+ 	 */
+ 	if (res->errFields == NULL)
+ 	{
+ 		if (res->errMsg && res->errMsg[0])
+ 			appendPQExpBufferStr(msg, res->errMsg);
+ 		else
+ 			appendPQExpBuffer(msg, libpq_gettext("no error message available\n"));
+ 		return;
+ 	}
+ 
+ 	/* Else build error message from relevant fields */
  	val = PQresultErrorField(res, PG_DIAG_SEVERITY);
  	if (val)
! 		appendPQExpBuffer(msg, "%s:  ", val);
! 	if (verbosity == PQERRORS_VERBOSE)
  	{
! 		val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
! 		if (val)
! 			appendPQExpBuffer(msg, "%s: ", val);
  	}
  	val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
  	if (val)
! 		appendPQExpBufferStr(msg, val);
  	val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
  	if (val)
  	{
! 		if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
  		{
  			/* emit position as a syntax cursor display */
! 			querytext = res->errQuery;
  			querypos = atoi(val);
  		}
  		else
  		{
  			/* emit position as text addition to primary message */
  			/* translator: %s represents a digit string */
! 			appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
  							  val);
  		}
  	}
*************** pqGetErrorNotice3(PGconn *conn, bool isE
*** 960,966 ****
  		if (val)
  		{
  			querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
! 			if (conn->verbosity != PQERRORS_TERSE && querytext != NULL)
  			{
  				/* emit position as a syntax cursor display */
  				querypos = atoi(val);
--- 1036,1042 ----
  		if (val)
  		{
  			querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
! 			if (verbosity != PQERRORS_TERSE && querytext != NULL)
  			{
  				/* emit position as a syntax cursor display */
  				querypos = atoi(val);
*************** pqGetErrorNotice3(PGconn *conn, bool isE
*** 969,1027 ****
  			{
  				/* emit position as text addition to primary message */
  				/* translator: %s represents a digit string */
! 				appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
  								  val);
  			}
  		}
  	}
! 	appendPQExpBufferChar(&workBuf, '\n');
! 	if (conn->verbosity != PQERRORS_TERSE)
  	{
  		if (querytext && querypos > 0)
! 			reportErrorPosition(&workBuf, querytext, querypos,
! 								conn->client_encoding);
  		val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
  		if (val)
! 			appendPQExpBuffer(&workBuf, libpq_gettext("DETAIL:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
  		if (val)
! 			appendPQExpBuffer(&workBuf, libpq_gettext("HINT:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
  		if (val)
! 			appendPQExpBuffer(&workBuf, libpq_gettext("QUERY:  %s\n"), val);
! 		if (conn->show_context == PQSHOW_CONTEXT_ALWAYS ||
! 			(conn->show_context == PQSHOW_CONTEXT_ERRORS && isError))
  		{
  			val = PQresultErrorField(res, PG_DIAG_CONTEXT);
  			if (val)
! 				appendPQExpBuffer(&workBuf, libpq_gettext("CONTEXT:  %s\n"),
  								  val);
  		}
  	}
! 	if (conn->verbosity == PQERRORS_VERBOSE)
  	{
  		val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
  		if (val)
! 			appendPQExpBuffer(&workBuf,
  							  libpq_gettext("SCHEMA NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
  		if (val)
! 			appendPQExpBuffer(&workBuf,
  							  libpq_gettext("TABLE NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
  		if (val)
! 			appendPQExpBuffer(&workBuf,
  							  libpq_gettext("COLUMN NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
  		if (val)
! 			appendPQExpBuffer(&workBuf,
  							  libpq_gettext("DATATYPE NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
  		if (val)
! 			appendPQExpBuffer(&workBuf,
  							  libpq_gettext("CONSTRAINT NAME:  %s\n"), val);
  	}
! 	if (conn->verbosity == PQERRORS_VERBOSE)
  	{
  		const char *valf;
  		const char *vall;
--- 1045,1104 ----
  			{
  				/* emit position as text addition to primary message */
  				/* translator: %s represents a digit string */
! 				appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
  								  val);
  			}
  		}
  	}
! 	appendPQExpBufferChar(msg, '\n');
! 	if (verbosity != PQERRORS_TERSE)
  	{
  		if (querytext && querypos > 0)
! 			reportErrorPosition(msg, querytext, querypos,
! 								res->client_encoding);
  		val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
  		if (val)
! 			appendPQExpBuffer(msg, libpq_gettext("DETAIL:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
  		if (val)
! 			appendPQExpBuffer(msg, libpq_gettext("HINT:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
  		if (val)
! 			appendPQExpBuffer(msg, libpq_gettext("QUERY:  %s\n"), val);
! 		if (show_context == PQSHOW_CONTEXT_ALWAYS ||
! 			(show_context == PQSHOW_CONTEXT_ERRORS &&
! 			 res->resultStatus == PGRES_FATAL_ERROR))
  		{
  			val = PQresultErrorField(res, PG_DIAG_CONTEXT);
  			if (val)
! 				appendPQExpBuffer(msg, libpq_gettext("CONTEXT:  %s\n"),
  								  val);
  		}
  	}
! 	if (verbosity == PQERRORS_VERBOSE)
  	{
  		val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
  		if (val)
! 			appendPQExpBuffer(msg,
  							  libpq_gettext("SCHEMA NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
  		if (val)
! 			appendPQExpBuffer(msg,
  							  libpq_gettext("TABLE NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
  		if (val)
! 			appendPQExpBuffer(msg,
  							  libpq_gettext("COLUMN NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
  		if (val)
! 			appendPQExpBuffer(msg,
  							  libpq_gettext("DATATYPE NAME:  %s\n"), val);
  		val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
  		if (val)
! 			appendPQExpBuffer(msg,
  							  libpq_gettext("CONSTRAINT NAME:  %s\n"), val);
  	}
! 	if (verbosity == PQERRORS_VERBOSE)
  	{
  		const char *valf;
  		const char *vall;
*************** pqGetErrorNotice3(PGconn *conn, bool isE
*** 1031,1081 ****
  		val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
  		if (val || valf || vall)
  		{
! 			appendPQExpBufferStr(&workBuf, libpq_gettext("LOCATION:  "));
  			if (val)
! 				appendPQExpBuffer(&workBuf, libpq_gettext("%s, "), val);
  			if (valf && vall)	/* unlikely we'd have just one */
! 				appendPQExpBuffer(&workBuf, libpq_gettext("%s:%s"),
  								  valf, vall);
! 			appendPQExpBufferChar(&workBuf, '\n');
! 		}
! 	}
! 
! 	/*
! 	 * Either save error as current async result, or just emit the notice.
! 	 */
! 	if (isError)
! 	{
! 		if (res)
! 			res->errMsg = pqResultStrdup(res, workBuf.data);
! 		pqClearAsyncResult(conn);
! 		conn->result = res;
! 		if (PQExpBufferDataBroken(workBuf))
! 			printfPQExpBuffer(&conn->errorMessage,
! 							  libpq_gettext("out of memory"));
! 		else
! 			appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
! 	}
! 	else
! 	{
! 		/* if we couldn't allocate the result set, just discard the NOTICE */
! 		if (res)
! 		{
! 			/* We can cheat a little here and not copy the message. */
! 			res->errMsg = workBuf.data;
! 			if (res->noticeHooks.noticeRec != NULL)
! 				(*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
! 			PQclear(res);
  		}
  	}
- 
- 	termPQExpBuffer(&workBuf);
- 	return 0;
- 
- fail:
- 	PQclear(res);
- 	termPQExpBuffer(&workBuf);
- 	return EOF;
  }
  
  /*
--- 1108,1122 ----
  		val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
  		if (val || valf || vall)
  		{
! 			appendPQExpBufferStr(msg, libpq_gettext("LOCATION:  "));
  			if (val)
! 				appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
  			if (valf && vall)	/* unlikely we'd have just one */
! 				appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
  								  valf, vall);
! 			appendPQExpBufferChar(msg, '\n');
  		}
  	}
  }
  
  /*
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 6bf34b3..9ca0756 100644
*** a/src/interfaces/libpq/libpq-fe.h
--- b/src/interfaces/libpq/libpq-fe.h
*************** extern PGresult *PQfn(PGconn *conn,
*** 463,468 ****
--- 463,471 ----
  extern ExecStatusType PQresultStatus(const PGresult *res);
  extern char *PQresStatus(ExecStatusType status);
  extern char *PQresultErrorMessage(const PGresult *res);
+ extern char *PQresultVerboseErrorMessage(const PGresult *res,
+ 							PGVerbosity verbosity,
+ 							PGContextVisibility show_context);
  extern char *PQresultErrorField(const PGresult *res, int fieldcode);
  extern int	PQntuples(const PGresult *res);
  extern int	PQnfields(const PGresult *res);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 6c9bbf7..1183323 100644
*** a/src/interfaces/libpq/libpq-int.h
--- b/src/interfaces/libpq/libpq-int.h
*************** struct pg_result
*** 197,202 ****
--- 197,203 ----
  	 */
  	char	   *errMsg;			/* error message, or NULL if no error */
  	PGMessageField *errFields;	/* message broken into fields */
+ 	char	   *errQuery;		/* text of triggering query, if available */
  
  	/* All NULL attributes in the query result point to this null string */
  	char		null_field[1];
*************** extern char *pqBuildStartupPacket3(PGcon
*** 575,580 ****
--- 576,583 ----
  					  const PQEnvironmentOption *options);
  extern void pqParseInput3(PGconn *conn);
  extern int	pqGetErrorNotice3(PGconn *conn, bool isError);
+ extern void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
+ 					 PGVerbosity verbosity, PGContextVisibility show_context);
  extern int	pqGetCopyData3(PGconn *conn, char **buffer, int async);
  extern int	pqGetline3(PGconn *conn, char *s, int maxlen);
  extern int	pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
