164 lines
4.2 KiB
C++
164 lines
4.2 KiB
C++
/*
|
|
* Copyright (c) 2018 MariaDB Corporation Ab
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
|
*
|
|
* Change Date: 2020-01-01
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2 or later of the General
|
|
* Public License.
|
|
*/
|
|
|
|
#include "utilities.hh"
|
|
|
|
#include <inttypes.h>
|
|
#include <limits>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <maxscale/debug.h>
|
|
#include <maxscale/mysql_utils.h>
|
|
|
|
using std::string;
|
|
|
|
/** Server id default value */
|
|
const int64_t SERVER_ID_UNKNOWN = -1;
|
|
|
|
int64_t scan_server_id(const char* id_string)
|
|
{
|
|
int64_t server_id = SERVER_ID_UNKNOWN;
|
|
ss_debug(int rv = ) sscanf(id_string, "%" PRId64, &server_id);
|
|
ss_dassert(rv == 1);
|
|
// Server id can be 0, which was even the default value until 10.2.1.
|
|
// KB is a bit hazy on this, but apparently when replicating, the server id should not be 0. Not sure,
|
|
// so MaxScale allows this.
|
|
#if defined(SS_DEBUG)
|
|
const int64_t SERVER_ID_MIN = std::numeric_limits<uint32_t>::min();
|
|
const int64_t SERVER_ID_MAX = std::numeric_limits<uint32_t>::max();
|
|
#endif
|
|
ss_dassert(server_id >= SERVER_ID_MIN && server_id <= SERVER_ID_MAX);
|
|
return server_id;
|
|
}
|
|
|
|
string get_connection_errors(const MonServerArray& servers)
|
|
{
|
|
// Get errors from all connections, form a string.
|
|
std::stringstream ss;
|
|
for (MonServerArray::const_iterator iter = servers.begin(); iter != servers.end(); iter++)
|
|
{
|
|
const char* error = mysql_error((*iter)->con);
|
|
ss_dassert(*error); // Every connection should have an error.
|
|
ss << (*iter)->server->unique_name << ": '" << error << "'";
|
|
if (iter + 1 != servers.end())
|
|
{
|
|
ss << ", ";
|
|
}
|
|
}
|
|
return ss.str();
|
|
}
|
|
|
|
string monitored_servers_to_string(const MonServerArray& array)
|
|
{
|
|
string rval;
|
|
size_t array_size = array.size();
|
|
if (array_size > 0)
|
|
{
|
|
const char* separator = "";
|
|
for (size_t i = 0; i < array_size; i++)
|
|
{
|
|
rval += separator;
|
|
rval += array[i]->server->unique_name;
|
|
separator = ",";
|
|
}
|
|
}
|
|
return rval;
|
|
}
|
|
|
|
QueryResult::QueryResult(MYSQL_RES* resultset)
|
|
: m_resultset(resultset)
|
|
, m_columns(-1)
|
|
, m_rowdata(NULL)
|
|
, m_current_row(-1)
|
|
{
|
|
if (m_resultset)
|
|
{
|
|
m_columns = mysql_num_fields(m_resultset);
|
|
MYSQL_FIELD* field_info = mysql_fetch_fields(m_resultset);
|
|
for (int64_t column_index = 0; column_index < m_columns; column_index++)
|
|
{
|
|
string key(field_info[column_index].name);
|
|
// TODO: Think of a way to handle duplicate names nicely. Currently this should only be used
|
|
// for known queries.
|
|
ss_dassert(m_col_indexes.count(key) == 0);
|
|
m_col_indexes[key] = column_index;
|
|
}
|
|
}
|
|
}
|
|
|
|
QueryResult::~QueryResult()
|
|
{
|
|
if (m_resultset)
|
|
{
|
|
mysql_free_result(m_resultset);
|
|
}
|
|
}
|
|
|
|
bool QueryResult::next_row()
|
|
{
|
|
m_rowdata = mysql_fetch_row(m_resultset);
|
|
if (m_rowdata != NULL)
|
|
{
|
|
m_current_row++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int64_t QueryResult::get_row_index() const
|
|
{
|
|
return m_current_row;
|
|
}
|
|
|
|
int64_t QueryResult::get_column_count() const
|
|
{
|
|
return m_columns;
|
|
}
|
|
|
|
int64_t QueryResult::get_col_index(const string& col_name) const
|
|
{
|
|
auto iter = m_col_indexes.find(col_name);
|
|
return (iter != m_col_indexes.end()) ? iter->second : -1;
|
|
}
|
|
|
|
string QueryResult::get_string(int64_t column_ind) const
|
|
{
|
|
ss_dassert(column_ind < m_columns);
|
|
char* data = m_rowdata[column_ind];
|
|
return data ? data : "";
|
|
}
|
|
|
|
int64_t QueryResult::get_uint(int64_t column_ind) const
|
|
{
|
|
ss_dassert(column_ind < m_columns);
|
|
char* data = m_rowdata[column_ind];
|
|
int64_t rval = -1;
|
|
if (data)
|
|
{
|
|
errno = 0; // strtoll sets this
|
|
auto parsed = strtoll(data, NULL, 10);
|
|
if (parsed >= 0 && errno == 0)
|
|
{
|
|
rval = parsed;
|
|
}
|
|
}
|
|
return rval;
|
|
}
|
|
|
|
bool QueryResult::get_bool(int64_t column_ind) const
|
|
{
|
|
ss_dassert(column_ind < m_columns);
|
|
char* data = m_rowdata[column_ind];
|
|
return data ? (strcmp(data,"Y") == 0 || strcmp(data, "1") == 0) : false;
|
|
}
|