in driver/execute.cc [42:217]
SQLRETURN do_query(STMT *stmt, std::string query)
{
int error= SQL_ERROR, native_error= 0;
SQLULEN query_length = query.length();
assert(stmt);
LOCK_STMT_DEFER(stmt);
if (query.empty())
{
/* Probably error from insert_param */
goto exit;
}
if(!SQL_SUCCEEDED(set_sql_select_limit(stmt->dbc,
stmt->stmt_options.max_rows, TRUE)))
{
/* The error is set for DBC, copy it into STMT */
stmt->set_error(stmt->dbc->error.sqlstate.c_str(),
stmt->dbc->error.message.c_str(),
stmt->dbc->error.native_error);
/* if setting sql_select_limit fails, the query will probably fail anyway too */
goto exit;
}
MYLOG_QUERY(stmt, query.c_str());
DO_LOCK_STMT();
if ( check_if_server_is_alive( stmt->dbc ) )
{
stmt->set_error("08S01" /* "HYT00" */,
mysql_error(stmt->dbc->mysql),
mysql_errno(stmt->dbc->mysql));
translate_error((char*)stmt->error.sqlstate.c_str(), MYERR_08S01 /* S1000 */,
mysql_errno(stmt->dbc->mysql));
goto exit;
}
/* Simplifying task so far - we will do "LIMIT" scrolling forward only
* and when no musltiple statements is allowed - we can't now parse query
* that well to detect multiple queries.
*/
if (stmt->dbc->ds.opt_PREFETCH > 0
&& !stmt->dbc->ds.opt_MULTI_STATEMENTS
&& stmt->stmt_options.cursor_type == SQL_CURSOR_FORWARD_ONLY
&& scrollable(stmt, query.c_str(), query.c_str() + query_length)
&& !ssps_used(stmt))
{
/* we might want to read primary key info at this point, but then we have to
know if we have a select from a single table...
*/
ssps_close(stmt);
stmt->scroller.reset();
stmt->scroller.row_count= calc_prefetch_number(
stmt->dbc->ds.opt_PREFETCH,
stmt->ard->array_size,
stmt->stmt_options.max_rows);
scroller_create(stmt, query.c_str(), query_length);
scroller_move(stmt);
MYLOG_QUERY(stmt, stmt->scroller.query);
native_error = mysql_real_query(stmt->dbc->mysql, stmt->scroller.query,
(unsigned long)stmt->scroller.query_len);
}
/* Not using ssps for scroller so far. Relaxing a bit condition
if MULTI_STATEMENTS option selected by primitive check if
this is a batch of queries */
else if (ssps_used(stmt))
{
native_error = stmt->bind_query_attrs(true);
if (native_error == SQL_ERROR) {
error = stmt->error.retcode;
goto exit;
}
native_error = mysql_stmt_execute(stmt->ssps);
MYLOG_QUERY(stmt, "ssps has been executed");
}
else
{
MYLOG_QUERY(stmt, "Using direct execution");
/* Need to close ps handler if it is open as our relsult will be generated
by direct execution. and ps handler may create some chaos */
ssps_close(stmt);
native_error = stmt->bind_query_attrs(false);
if (native_error == SQL_ERROR)
{
error = stmt->error.retcode;
goto exit;
}
native_error= mysql_real_query(stmt->dbc->mysql, query.c_str(),
(unsigned long)query_length);
}
MYLOG_QUERY(stmt, "query has been executed");
if (native_error)
{
error = stmt->set_error("HY000");
MYLOG_QUERY(stmt, stmt->error.message.c_str());
/* For some errors - translating to more appropriate status */
translate_error((char*)stmt->error.sqlstate.c_str(), MYERR_S1000,
stmt->error.native_error);
goto exit;
}
if (!get_result_metadata(stmt, FALSE))
{
/* Query was supposed to return result, but result is NULL*/
if (returned_result(stmt))
{
error = stmt->set_error(MYERR_S1000);
goto exit;
}
else /* Query was not supposed to return a result */
{
error= SQL_SUCCESS; /* no result set */
stmt->state= ST_EXECUTED;
update_affected_rows(stmt);
// The query without results can end spans here.
stmt->telemetry.span_end(stmt);
goto exit;
}
}
if (bind_result(stmt) || get_result(stmt))
{
error = stmt->set_error(MYERR_S1000);
goto exit;
}
/* Caching row counts for queries returning resultset as well */
//update_affected_rows(stmt);
fix_result_types(stmt);
/* If the only resultset is OUT params, then we can only detect
corresponding server_status right after execution.
If the RS is OUT params - we do not need to do store_result obviously */
if (IS_PS_OUT_PARAMS(stmt))
{
/* This status(SERVER_PS_OUT_PARAMS) can be only if we used PS */
ssps_get_out_params(stmt);
if (stmt->out_params_state == OPS_STREAMS_PENDING)
{
error= SQL_PARAM_DATA_AVAILABLE;
goto exit;
}
}
error= SQL_SUCCESS;
exit:
if (!SQL_SUCCEEDED(error)) {
stmt->telemetry.set_error(stmt, stmt->error.message);
}
/*
If the original query was modified, we reset stmt->query so that the
next execution re-starts with the original query.
*/
if (GET_QUERY(&stmt->orig_query))
{
stmt->query = stmt->orig_query;
stmt->orig_query.reset(NULL, NULL, NULL);
}
return error;
}