SQLRETURN do_query()

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;
}