@ -876,11 +876,9 @@ int
pqGetErrorNotice3 ( PGconn * conn , bool isError )
pqGetErrorNotice3 ( PGconn * conn , bool isError )
{
{
PGresult * res = NULL ;
PGresult * res = NULL ;
bool have_position = false ;
PQExpBufferData workBuf ;
PQExpBufferData workBuf ;
char id ;
char id ;
const char * val ;
const char * querytext = NULL ;
int querypos = 0 ;
/*
/*
* Since the fields might be pretty long , we create a temporary
* Since the fields might be pretty long , we create a temporary
@ -905,6 +903,9 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
/*
/*
* Read the fields and save into res .
* Read the fields and save into res .
*
* While at it , save the SQLSTATE in conn - > last_sqlstate , and note whether
* we saw a PG_DIAG_STATEMENT_POSITION field .
*/
*/
for ( ; ; )
for ( ; ; )
{
{
@ -915,42 +916,123 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
if ( pqGets ( & workBuf , conn ) )
if ( pqGets ( & workBuf , conn ) )
goto fail ;
goto fail ;
pqSaveMessageField ( res , id , workBuf . data ) ;
pqSaveMessageField ( res , id , workBuf . data ) ;
if ( id = = PG_DIAG_SQLSTATE )
strlcpy ( conn - > last_sqlstate , workBuf . data ,
sizeof ( conn - > last_sqlstate ) ) ;
else if ( id = = PG_DIAG_STATEMENT_POSITION )
have_position = true ;
}
}
/*
* Save the active query text , if any , into res as well ; but only if we
* might need it for an error cursor display , which is only true if there
* is a PG_DIAG_STATEMENT_POSITION field .
*/
if ( have_position & & conn - > last_query & & res )
res - > errQuery = pqResultStrdup ( res , conn - > last_query ) ;
/*
/*
* Now build the " overall " error message for PQresultErrorMessage .
* Now build the " overall " error message for PQresultErrorMessage .
*
* Also , save the SQLSTATE in conn - > last_sqlstate .
*/
*/
resetPQExpBuffer ( & workBuf ) ;
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 ) ;
val = PQresultErrorField ( res , PG_DIAG_SEVERITY ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf , " %s: " , val ) ;
appendPQExpBuffer ( msg , " %s: " , val ) ;
val = PQresultErrorField ( res , PG_DIAG_SQLSTATE ) ;
if ( verbosity = = PQERRORS_VERBOSE )
if ( val )
{
{
if ( strlen ( val ) < sizeof ( conn - > last_sqlstate ) )
val = PQresultErrorField ( res , PG_DIAG_SQLSTATE ) ;
strcpy ( conn - > last_sqlstate , val ) ;
if ( val )
if ( conn - > verbosity = = PQERRORS_VERBOSE )
appendPQExpBuffer ( msg , " %s: " , val ) ;
appendPQExpBuffer ( & workBuf , " %s: " , val ) ;
}
}
val = PQresultErrorField ( res , PG_DIAG_MESSAGE_PRIMARY ) ;
val = PQresultErrorField ( res , PG_DIAG_MESSAGE_PRIMARY ) ;
if ( val )
if ( val )
appendPQExpBufferStr ( & workBuf , val ) ;
appendPQExpBufferStr ( msg , val ) ;
val = PQresultErrorField ( res , PG_DIAG_STATEMENT_POSITION ) ;
val = PQresultErrorField ( res , PG_DIAG_STATEMENT_POSITION ) ;
if ( val )
if ( val )
{
{
if ( conn - > verbosity ! = PQERRORS_TERSE & & conn - > last_query ! = NULL )
if ( verbosity ! = PQERRORS_TERSE & & res - > errQ uery ! = NULL )
{
{
/* emit position as a syntax cursor display */
/* emit position as a syntax cursor display */
querytext = conn - > last_query ;
querytext = res - > errQ uery;
querypos = atoi ( val ) ;
querypos = atoi ( val ) ;
}
}
else
else
{
{
/* emit position as text addition to primary message */
/* emit position as text addition to primary message */
/* translator: %s represents a digit string */
/* translator: %s represents a digit string */
appendPQExpBuffer ( & workBuf , libpq_gettext ( " at character %s " ) ,
appendPQExpBuffer ( msg , libpq_gettext ( " at character %s " ) ,
val ) ;
val ) ;
}
}
}
}
@ -960,7 +1042,7 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
if ( val )
if ( val )
{
{
querytext = PQresultErrorField ( res , PG_DIAG_INTERNAL_QUERY ) ;
querytext = PQresultErrorField ( res , PG_DIAG_INTERNAL_QUERY ) ;
if ( conn - > verbosity ! = PQERRORS_TERSE & & querytext ! = NULL )
if ( verbosity ! = PQERRORS_TERSE & & querytext ! = NULL )
{
{
/* emit position as a syntax cursor display */
/* emit position as a syntax cursor display */
querypos = atoi ( val ) ;
querypos = atoi ( val ) ;
@ -969,59 +1051,60 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
{
{
/* emit position as text addition to primary message */
/* emit position as text addition to primary message */
/* translator: %s represents a digit string */
/* translator: %s represents a digit string */
appendPQExpBuffer ( & workBuf , libpq_gettext ( " at character %s " ) ,
appendPQExpBuffer ( msg , libpq_gettext ( " at character %s " ) ,
val ) ;
val ) ;
}
}
}
}
}
}
appendPQExpBufferChar ( & workBuf , ' \n ' ) ;
appendPQExpBufferChar ( msg , ' \n ' ) ;
if ( conn - > verbosity ! = PQERRORS_TERSE )
if ( verbosity ! = PQERRORS_TERSE )
{
{
if ( querytext & & querypos > 0 )
if ( querytext & & querypos > 0 )
reportErrorPosition ( & workBuf , querytext , querypos ,
reportErrorPosition ( msg , querytext , querypos ,
conn - > client_encoding ) ;
res - > client_encoding ) ;
val = PQresultErrorField ( res , PG_DIAG_MESSAGE_DETAIL ) ;
val = PQresultErrorField ( res , PG_DIAG_MESSAGE_DETAIL ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf , libpq_gettext ( " DETAIL: %s \n " ) , val ) ;
appendPQExpBuffer ( msg , libpq_gettext ( " DETAIL: %s \n " ) , val ) ;
val = PQresultErrorField ( res , PG_DIAG_MESSAGE_HINT ) ;
val = PQresultErrorField ( res , PG_DIAG_MESSAGE_HINT ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf , libpq_gettext ( " HINT: %s \n " ) , val ) ;
appendPQExpBuffer ( msg , libpq_gettext ( " HINT: %s \n " ) , val ) ;
val = PQresultErrorField ( res , PG_DIAG_INTERNAL_QUERY ) ;
val = PQresultErrorField ( res , PG_DIAG_INTERNAL_QUERY ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf , libpq_gettext ( " QUERY: %s \n " ) , val ) ;
appendPQExpBuffer ( msg , libpq_gettext ( " QUERY: %s \n " ) , val ) ;
if ( conn - > show_context = = PQSHOW_CONTEXT_ALWAYS | |
if ( show_context = = PQSHOW_CONTEXT_ALWAYS | |
( conn - > show_context = = PQSHOW_CONTEXT_ERRORS & & isError ) )
( show_context = = PQSHOW_CONTEXT_ERRORS & &
res - > resultStatus = = PGRES_FATAL_ERROR ) )
{
{
val = PQresultErrorField ( res , PG_DIAG_CONTEXT ) ;
val = PQresultErrorField ( res , PG_DIAG_CONTEXT ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf , libpq_gettext ( " CONTEXT: %s \n " ) ,
appendPQExpBuffer ( msg , libpq_gettext ( " CONTEXT: %s \n " ) ,
val ) ;
val ) ;
}
}
}
}
if ( conn - > verbosity = = PQERRORS_VERBOSE )
if ( verbosity = = PQERRORS_VERBOSE )
{
{
val = PQresultErrorField ( res , PG_DIAG_SCHEMA_NAME ) ;
val = PQresultErrorField ( res , PG_DIAG_SCHEMA_NAME ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf ,
appendPQExpBuffer ( msg ,
libpq_gettext ( " SCHEMA NAME: %s \n " ) , val ) ;
libpq_gettext ( " SCHEMA NAME: %s \n " ) , val ) ;
val = PQresultErrorField ( res , PG_DIAG_TABLE_NAME ) ;
val = PQresultErrorField ( res , PG_DIAG_TABLE_NAME ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf ,
appendPQExpBuffer ( msg ,
libpq_gettext ( " TABLE NAME: %s \n " ) , val ) ;
libpq_gettext ( " TABLE NAME: %s \n " ) , val ) ;
val = PQresultErrorField ( res , PG_DIAG_COLUMN_NAME ) ;
val = PQresultErrorField ( res , PG_DIAG_COLUMN_NAME ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf ,
appendPQExpBuffer ( msg ,
libpq_gettext ( " COLUMN NAME: %s \n " ) , val ) ;
libpq_gettext ( " COLUMN NAME: %s \n " ) , val ) ;
val = PQresultErrorField ( res , PG_DIAG_DATATYPE_NAME ) ;
val = PQresultErrorField ( res , PG_DIAG_DATATYPE_NAME ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf ,
appendPQExpBuffer ( msg ,
libpq_gettext ( " DATATYPE NAME: %s \n " ) , val ) ;
libpq_gettext ( " DATATYPE NAME: %s \n " ) , val ) ;
val = PQresultErrorField ( res , PG_DIAG_CONSTRAINT_NAME ) ;
val = PQresultErrorField ( res , PG_DIAG_CONSTRAINT_NAME ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf ,
appendPQExpBuffer ( msg ,
libpq_gettext ( " CONSTRAINT NAME: %s \n " ) , val ) ;
libpq_gettext ( " CONSTRAINT NAME: %s \n " ) , val ) ;
}
}
if ( conn - > verbosity = = PQERRORS_VERBOSE )
if ( verbosity = = PQERRORS_VERBOSE )
{
{
const char * valf ;
const char * valf ;
const char * vall ;
const char * vall ;
@ -1031,51 +1114,15 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
val = PQresultErrorField ( res , PG_DIAG_SOURCE_FUNCTION ) ;
val = PQresultErrorField ( res , PG_DIAG_SOURCE_FUNCTION ) ;
if ( val | | valf | | vall )
if ( val | | valf | | vall )
{
{
appendPQExpBufferStr ( & workBuf , libpq_gettext ( " LOCATION: " ) ) ;
appendPQExpBufferStr ( msg , libpq_gettext ( " LOCATION: " ) ) ;
if ( val )
if ( val )
appendPQExpBuffer ( & workBuf , libpq_gettext ( " %s, " ) , val ) ;
appendPQExpBuffer ( msg , libpq_gettext ( " %s, " ) , val ) ;
if ( valf & & vall ) /* unlikely we'd have just one */
if ( valf & & vall ) /* unlikely we'd have just one */
appendPQExpBuffer ( & workBuf , libpq_gettext ( " %s:%s " ) ,
appendPQExpBuffer ( msg , libpq_gettext ( " %s:%s " ) ,
valf , vall ) ;
valf , vall ) ;
appendPQExpBufferChar ( & workBuf , ' \n ' ) ;
appendPQExpBufferChar ( msg , ' \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 ;
}
}
/*
/*