in driver/my_prepared_stmt.cc [85:247]
BOOL ssps_get_out_params(STMT *stmt)
{
/* If we use prepared statement, and the query is CALL and we have any
user's parameter described as INOUT or OUT and that is only result */
if (is_call_procedure(&stmt->query))
{
MYSQL_ROW values= NULL;
DESCREC *iprec, *aprec;
uint counter= 0;
int i, out_params;
/*Since OUT parameters can be completely different - we have to free current
bind and bind new */
free_result_bind(stmt);
/* Thus function interface has to be changed */
if (stmt->ssps_bind_result() == 0)
{
try
{
values = stmt->fetch_row();
}
catch(MYERROR&)
{
return FALSE;
}
/* We need this for fetch_varlength_columns pointed by fix_fields, so it omits
streamed parameters */
out_params= got_out_parameters(stmt);
if (out_params & GOT_OUT_STREAM_PARAMETERS)
{
stmt->out_params_state= OPS_STREAMS_PENDING;
stmt->current_param= ~0L;
stmt->reset_getdata_position();
}
else//(out_params & GOT_OUT_PARAMETERS)
{
stmt->out_params_state= OPS_PREFETCHED;
}
if (stmt->fix_fields)
{
values= (*stmt->fix_fields)(stmt,values);
}
}
assert(values);
if (values)
{
stmt->current_values= values;
if (out_params)
{
for (i= 0;
i < myodbc_min(stmt->ipd->rcount(), stmt->apd->rcount()) && counter < stmt->field_count();
++i)
{
/* Making bit field look "normally" */
if (stmt->result_bind[counter].buffer_type == MYSQL_TYPE_BIT)
{
MYSQL_FIELD *field= mysql_fetch_field_direct(stmt->result, counter);
unsigned long long numeric;
assert(field->type == MYSQL_TYPE_BIT);
/* terminating with NULL */
values[counter][*stmt->result_bind[counter].length]= '\0';
numeric= strtoull(values[counter], NULL, 10);
*stmt->result_bind[counter].length= (field->length+7)/8;
numeric2binary(values[counter], numeric,
*stmt->result_bind[counter].length);
}
iprec= desc_get_rec(stmt->ipd, i, FALSE);
aprec= desc_get_rec(stmt->apd, i, FALSE);
assert(iprec && aprec);
if (iprec->parameter_type == SQL_PARAM_INPUT_OUTPUT
|| iprec->parameter_type == SQL_PARAM_OUTPUT
#ifndef USE_IODBC
|| iprec->parameter_type == SQL_PARAM_INPUT_OUTPUT_STREAM
|| iprec->parameter_type == SQL_PARAM_OUTPUT_STREAM
#endif
)
{
if (aprec->data_ptr)
{
unsigned long length= *stmt->result_bind[counter].length;
char *target= NULL;
SQLLEN *octet_length_ptr= NULL;
SQLLEN *indicator_ptr= NULL;
SQLINTEGER default_size;
if (aprec->octet_length_ptr)
{
octet_length_ptr= (SQLLEN*)ptr_offset_adjust(aprec->octet_length_ptr,
stmt->apd->bind_offset_ptr,
stmt->apd->bind_type,
sizeof(SQLLEN), 0);
}
indicator_ptr= (SQLLEN*)ptr_offset_adjust(aprec->indicator_ptr,
stmt->apd->bind_offset_ptr,
stmt->apd->bind_type,
sizeof(SQLLEN), 0);
default_size = bind_length(aprec->concise_type,
(ulong)aprec->octet_length);
target= (char*)ptr_offset_adjust(aprec->data_ptr, stmt->apd->bind_offset_ptr,
stmt->apd->bind_type, default_size, 0);
stmt->reset_getdata_position();
if (iprec->parameter_type == SQL_PARAM_INPUT_OUTPUT
|| iprec->parameter_type == SQL_PARAM_OUTPUT)
{
sql_get_data(stmt, aprec->concise_type, counter,
target, aprec->octet_length, indicator_ptr,
values[counter], length, aprec);
/* TODO: solve that globally */
if (octet_length_ptr != NULL && indicator_ptr != NULL
&& octet_length_ptr != indicator_ptr
&& *indicator_ptr != SQL_NULL_DATA)
{
*octet_length_ptr= *indicator_ptr;
}
}
else if (octet_length_ptr != NULL)
{
/* Putting full number of bytes in the stream. A bit dirtyhackish.
Only good since only binary type is supported... */
*octet_length_ptr= *stmt->result_bind[counter].length;
}
}
++counter;
}
}
}
}
else /*values != NULL */
{
/* Something went wrong */
stmt->out_params_state= OPS_UNKNOWN;
}
if (stmt->out_params_state != OPS_STREAMS_PENDING)
{
/* This MAGICAL fetch is required. If there are streams - it has to be after
streams are all done, perhaps when stmt->out_params_state is changed from
OPS_STREAMS_PENDING */
mysql_stmt_fetch(stmt->ssps);
}
return TRUE;
}
return FALSE;
}