@ -1614,6 +1614,8 @@ exec_bind_message(StringInfo input_message)
bool save_log_statement_stats = log_statement_stats ;
bool snapshot_set = false ;
char msec_str [ 32 ] ;
ParamsErrorCbData params_data ;
ErrorContextCallback params_errcxt ;
/* Get the fixed part of the message */
portal_name = pq_getmsgstring ( input_message ) ;
@ -1753,6 +1755,8 @@ exec_bind_message(StringInfo input_message)
*/
if ( numParams > 0 )
{
char * * knownTextValues = NULL ; /* allocate on first use */
params = makeParamList ( numParams ) ;
for ( int paramno = 0 ; paramno < numParams ; paramno + + )
@ -1820,9 +1824,32 @@ exec_bind_message(StringInfo input_message)
pval = OidInputFunctionCall ( typinput , pstring , typioparam , - 1 ) ;
/* Free result of encoding conversion, if any */
if ( pstring & & pstring ! = pbuf . data )
pfree ( pstring ) ;
/*
* Free result of encoding conversion , if any , and save a copy
* for later when logging parameters .
*/
if ( pstring )
{
if ( log_parameters_on_error )
{
MemoryContext oldcxt ;
oldcxt = MemoryContextSwitchTo ( MessageContext ) ;
if ( knownTextValues = = NULL )
knownTextValues =
palloc0 ( numParams * sizeof ( char * ) ) ;
/*
* Note : must copy at least two more full characters
* than BuildParamLogString wants to see ; otherwise it
* might fail to include the ellipsis .
*/
knownTextValues [ paramno ] =
pnstrdup ( pstring , 64 + 2 * MAX_MULTIBYTE_CHAR_LEN ) ;
MemoryContextSwitchTo ( oldcxt ) ;
}
if ( pstring ! = pbuf . data )
pfree ( pstring ) ;
}
}
else if ( pformat = = 1 ) /* binary mode */
{
@ -1872,6 +1899,15 @@ exec_bind_message(StringInfo input_message)
params - > params [ paramno ] . pflags = PARAM_FLAG_CONST ;
params - > params [ paramno ] . ptype = ptype ;
}
/*
* Once all parameters have been received , prepare for printing them in
* errors , if configured to do so . ( This is saved in the portal , so
* that they ' ll appear when the query is executed later . )
*/
if ( log_parameters_on_error )
params - > paramValuesStr =
BuildParamLogString ( params , knownTextValues , 64 ) ;
}
else
params = NULL ;
@ -1879,6 +1915,14 @@ exec_bind_message(StringInfo input_message)
/* Done storing stuff in portal's context */
MemoryContextSwitchTo ( oldContext ) ;
/* Set the error callback so that parameters are logged, as needed */
params_data . portalName = portal - > name ;
params_data . params = params ;
params_errcxt . previous = error_context_stack ;
params_errcxt . callback = ParamsErrorCallback ;
params_errcxt . arg = ( void * ) & params_data ;
error_context_stack = & params_errcxt ;
/* Get the result format codes */
numRFormats = pq_getmsgint ( input_message , 2 ) ;
if ( numRFormats > 0 )
@ -1924,6 +1968,12 @@ exec_bind_message(StringInfo input_message)
*/
PortalSetResultFormat ( portal , numRFormats , rformats ) ;
/*
* Done binding ; remove the parameters error callback . Entries emitted
* later determine independently whether to log the parameters or not .
*/
error_context_stack = error_context_stack - > previous ;
/*
* Send BindComplete .
*/
@ -1980,6 +2030,8 @@ exec_execute_message(const char *portal_name, long max_rows)
bool execute_is_fetch ;
bool was_logged = false ;
char msec_str [ 32 ] ;
ParamsErrorCbData params_data ;
ErrorContextCallback params_errcxt ;
/* Adjust destination to tell printtup.c what to do */
dest = whereToSendOutput ;
@ -2104,8 +2156,16 @@ exec_execute_message(const char *portal_name, long max_rows)
CHECK_FOR_INTERRUPTS ( ) ;
/*
* Okay to run the portal .
* Okay to run the portal . Set the error callback so that parameters are
* logged . The parameters must have been saved during the bind phase .
*/
params_data . portalName = portal - > name ;
params_data . params = portalParams ;
params_errcxt . previous = error_context_stack ;
params_errcxt . callback = ParamsErrorCallback ;
params_errcxt . arg = ( void * ) & params_data ;
error_context_stack = & params_errcxt ;
if ( max_rows < = 0 )
max_rows = FETCH_ALL ;
@ -2119,6 +2179,9 @@ exec_execute_message(const char *portal_name, long max_rows)
receiver - > rDestroy ( receiver ) ;
/* Done executing; remove the params error callback */
error_context_stack = error_context_stack - > previous ;
if ( completed )
{
if ( is_xact_command )
@ -2329,51 +2392,13 @@ errdetail_execute(List *raw_parsetree_list)
static int
errdetail_params ( ParamListInfo params )
{
/* We mustn't call user-defined I/O functions when in an aborted xact */
if ( params & & params - > numParams > 0 & & ! IsAbortedTransactionBlockState ( ) )
if ( params & & params - > numParams > 0 )
{
StringInfoData param_str ;
MemoryContext oldcontext ;
char * str ;
/* This code doesn't support dynamic param lists */
Assert ( params - > paramFetch = = NULL ) ;
/* Make sure any trash is generated in MessageContext */
oldcontext = MemoryContextSwitchTo ( MessageContext ) ;
initStringInfo ( & param_str ) ;
for ( int paramno = 0 ; paramno < params - > numParams ; paramno + + )
{
ParamExternData * prm = & params - > params [ paramno ] ;
Oid typoutput ;
bool typisvarlena ;
char * pstring ;
appendStringInfo ( & param_str , " %s$%d = " ,
paramno > 0 ? " , " : " " ,
paramno + 1 ) ;
if ( prm - > isnull | | ! OidIsValid ( prm - > ptype ) )
{
appendStringInfoString ( & param_str , " NULL " ) ;
continue ;
}
getTypeOutputInfo ( prm - > ptype , & typoutput , & typisvarlena ) ;
pstring = OidOutputFunctionCall ( typoutput , prm - > value ) ;
appendStringInfoStringQuoted ( & param_str , pstring , 0 ) ;
pfree ( pstring ) ;
}
errdetail ( " parameters: %s " , param_str . data ) ;
pfree ( param_str . data ) ;
MemoryContextSwitchTo ( oldcontext ) ;
str = BuildParamLogString ( params , NULL , 0 ) ;
if ( str & & str [ 0 ] ! = ' \0 ' )
errdetail ( " parameters: %s " , str ) ;
}
return 0 ;