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