MXS-1703 Add convenience function + class for querying and storing results
An object of the class is returned as an auto_ptr to simplify memory management.
This commit is contained in:
@ -15,7 +15,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <maxscale/mysql_utils.h>
|
||||
#include "utilities.hh"
|
||||
|
||||
Gtid::Gtid()
|
||||
@ -116,3 +116,18 @@ int64_t MariaDBServer::relay_log_events()
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::auto_ptr<QueryResult> MariaDBServer::execute_query(const string& query)
|
||||
{
|
||||
auto conn = server_base->con;
|
||||
std::auto_ptr<QueryResult> rval;
|
||||
MYSQL_RES *result = NULL;
|
||||
if (mxs_mysql_query(conn, query.c_str()) == 0 && (result = mysql_store_result(conn)) != NULL)
|
||||
{
|
||||
rval = std::auto_ptr<QueryResult>(new QueryResult(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
mon_report_query_error(server_base);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
@ -16,10 +16,10 @@
|
||||
#include <maxscale/cppdefs.hh>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <memory>
|
||||
#include <maxscale/monitor.h>
|
||||
#include "utilities.hh"
|
||||
|
||||
using std::string;
|
||||
enum mysql_server_version
|
||||
{
|
||||
MYSQL_SERVER_VERSION_100,
|
||||
@ -47,7 +47,7 @@ public:
|
||||
|
||||
bool operator == (const Gtid& rhs) const;
|
||||
|
||||
string to_string() const;
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* Generate a MASTER_GTID_WAIT()-query to this gtid.
|
||||
@ -55,7 +55,7 @@ public:
|
||||
* @param timeout Maximum wait time in seconds
|
||||
* @return The query
|
||||
*/
|
||||
string generate_master_gtid_wait_cmd(double timeout) const;
|
||||
std::string generate_master_gtid_wait_cmd(double timeout) const;
|
||||
|
||||
private:
|
||||
void parse_triplet(const char* str);
|
||||
@ -67,17 +67,17 @@ class SlaveStatusInfo
|
||||
public:
|
||||
int64_t master_server_id; /**< The master's server_id value. Valid ids are 32bit unsigned. -1 is
|
||||
* unread/error. */
|
||||
string master_host; /**< Master server host name. */
|
||||
std::string master_host; /**< Master server host name. */
|
||||
int master_port; /**< Master server port. */
|
||||
bool slave_io_running; /**< Whether the slave I/O thread is running and connected. */
|
||||
bool slave_sql_running; /**< Whether or not the SQL thread is running. */
|
||||
string master_log_file; /**< Name of the master binary log file that the I/O thread is currently
|
||||
std::string master_log_file; /**< Name of the master binary log file that the I/O thread is currently
|
||||
* reading from. */
|
||||
uint64_t read_master_log_pos; /**< Position up to which the I/O thread has read in the current master
|
||||
* binary log file. */
|
||||
Gtid gtid_io_pos; /**< Gtid I/O position of the slave thread. Only shows the triplet with
|
||||
* the current master domain. */
|
||||
string last_error; /**< Last IO or SQL error encountered. */
|
||||
std::string last_error; /**< Last IO or SQL error encountered. */
|
||||
|
||||
SlaveStatusInfo();
|
||||
};
|
||||
@ -137,4 +137,14 @@ public:
|
||||
* an error in the gtid-values.
|
||||
*/
|
||||
int64_t relay_log_events();
|
||||
|
||||
/**
|
||||
* Execute a query which returns data. The results are returned as an auto-pointer to a QueryResult
|
||||
* object.
|
||||
*
|
||||
* @param query The query
|
||||
* @return Pointer to query results, or an empty auto-ptr on failure. Currently, the column names of the
|
||||
* results are assumed unique.
|
||||
*/
|
||||
std::auto_ptr<QueryResult> execute_query(const std::string& query);
|
||||
};
|
||||
@ -113,3 +113,81 @@ string monitored_servers_to_string(const ServerVector& array)
|
||||
}
|
||||
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_int(int64_t column_ind) const
|
||||
{
|
||||
ss_dassert(column_ind < m_columns);
|
||||
char* data = m_rowdata[column_ind];
|
||||
errno = 0; // strtoll sets this
|
||||
return data ? strtoll(data, NULL, 10) : 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -71,3 +71,79 @@ string get_connection_errors(const ServerVector& servers);
|
||||
* @return Server names
|
||||
*/
|
||||
string monitored_servers_to_string(const ServerVector& array);
|
||||
|
||||
/**
|
||||
* Helper class for simplifying working with resultsets. Used in MariaDBServer.
|
||||
*/
|
||||
class QueryResult
|
||||
{
|
||||
// These need to be banned to avoid premature destruction.
|
||||
QueryResult(const QueryResult&) = delete;
|
||||
QueryResult& operator = (const QueryResult&) = delete;
|
||||
|
||||
public:
|
||||
QueryResult(MYSQL_RES* resultset = NULL);
|
||||
~QueryResult();
|
||||
|
||||
/**
|
||||
* Advance to next row. Affects all result returning functions.
|
||||
*
|
||||
* @return True if the next row has data, false if the current row was the last one.
|
||||
*/
|
||||
bool next_row();
|
||||
|
||||
/**
|
||||
* Get the index of the current row.
|
||||
*
|
||||
* @return Current row index, or -1 if no data or next_row() has not been called yet.
|
||||
*/
|
||||
int64_t get_row_index() const;
|
||||
|
||||
/**
|
||||
* How many columns the result set has.
|
||||
*
|
||||
* @return Column count, or -1 if no data.
|
||||
*/
|
||||
int64_t get_column_count() const;
|
||||
|
||||
/**
|
||||
* Get a numeric index for a column name. May give wrong results if column names are not unique.
|
||||
*
|
||||
* @param col_name Column name
|
||||
* @return Index or -1 if not found.
|
||||
*/
|
||||
int64_t get_col_index(const string& col_name) const;
|
||||
|
||||
/**
|
||||
* Read a string value from the current row and given column. Empty string and (null) are both interpreted
|
||||
* as the empty string.
|
||||
*
|
||||
* @param column_ind Column index
|
||||
* @return Value as string
|
||||
*/
|
||||
string get_string(int64_t column_ind) const;
|
||||
|
||||
/**
|
||||
* Read an integer value from the current row and given column. No error checking is done on the parsing.
|
||||
* The parsing is performed by @c strtoll(), so the caller may check errno for errors.
|
||||
*
|
||||
* @param column_ind Column index
|
||||
* @return Value as integer
|
||||
*/
|
||||
int64_t get_int(int64_t column_ind) const;
|
||||
|
||||
/**
|
||||
* Read a boolean value from the current row and given column.
|
||||
*
|
||||
* @param column_ind Column index
|
||||
* @return Value as boolean. Returns true if the text is either 'Y' or '1'.
|
||||
*/
|
||||
bool get_bool(int64_t column_ind) const;
|
||||
|
||||
private:
|
||||
MYSQL_RES* m_resultset; // Underlying result set, freed at dtor.
|
||||
std::tr1::unordered_map<string, int64_t> m_col_indexes; // Map of column name -> index
|
||||
int64_t m_columns; // How many columns does the data have. Usually equal to column index map size.
|
||||
MYSQL_ROW m_rowdata; // Data for current row
|
||||
int64_t m_current_row; // Index of current row
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user