polardbxengine/client/base/mysql_query_runner.h

237 lines
7.8 KiB
C++

/*
Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is also distributed with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have included with MySQL.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MYSQL_QUERY_RUNNER_INCLUDED
#define MYSQL_QUERY_RUNNER_INCLUDED
#include <algorithm>
#include <atomic>
#include <functional>
#include <string>
#include <vector>
#include "client/base/message_data.h"
#include "my_inttypes.h"
#include "mysql.h"
namespace Mysql {
namespace Tools {
namespace Base {
/**
Helper class to run SQL query on existing MySQL database server connection,
receive all data and all errors, warnings and notes returned during query
execution. All acquired information is passed to set of callbacks to make
data flows more customizable.
*/
class Mysql_query_runner {
public:
class Row;
/**
Standard constructor based on MySQL connection.
*/
Mysql_query_runner(MYSQL *connection);
/**
Copy constructor.
*/
Mysql_query_runner(const Mysql_query_runner &source);
~Mysql_query_runner();
/**
Adds new callback to be called on every result row of query.
If callback return value other than 0 then query execution, passing
current row to other callbacks and error messages processing, and
Mysql_query_runner::run_query() will return value returned from this
callback.
Callbacks are called in reverse order of addition, i.e. newest are first.
*/
Mysql_query_runner &add_result_callback(
std::function<int64(const Row &)> *result_callback);
/**
Adds new callback to be called on every message after query execution,
this includes errors, warnings and other notes. Return value from callback
of 0 will lead to next handler being called, positive number return value
will cause Mysql_query_runner::run_query() will return immediately this
value and negative number will continue query execution and other messages
processing, but will not pass current message to rest of callbacks.
Callbacks are called in reverse order of addition, i.e. newest are first.
The optional cleanup function is called when the callback is deleted.
*/
Mysql_query_runner &add_message_callback(
std::function<int64(const Message_data &)> *message_callback,
std::function<void()> cleanup_callback = nullptr);
/**
Runs specified query and processes result rows and messages to callbacks.
*/
int64 run_query(std::string query);
/**
Runs specified query, fills result vector with processed result rows
and processes messages to callbacks.
*/
int64 run_query_store(std::string query, std::vector<const Row *> *result);
/**
Runs specified query with result callback specified. Does not add specified
callback to list of callbacks, next queries will not process rows to this
callback.
*/
int64 run_query(std::string query,
std::function<int64(const Row &)> *result_callback);
/**
Returns escaped copy of string to use in queries.
*/
std::string escape_string(const std::string &original);
/**
Escapes specified input string and appends it escaped to destination
string.
*/
void append_escape_string(std::string *destination_string,
const std::string &original);
/**
Escapes specified input string specified as characters buffer and its size,
and appends it escaped to destination string.
*/
void append_escape_string(std::string *destination_string,
const char *original, size_t original_length);
/**
Converts to HEX specified input string specified as characters buffer and
its size, and appends it escaped to destination string.
*/
static void append_hex_string(std::string *destination_string,
const char *original, size_t original_length);
/**
Empties memory used by result strings.
*/
static void cleanup_result(const Row &result);
/**
Empties memory used by result strings.
*/
static void cleanup_result(std::vector<const Row *> *result);
MYSQL *get_low_level_connection() const;
class Row {
public:
class Iterator;
Row(MYSQL_RES *mysql_result_info, unsigned int column_count, MYSQL_ROW row);
~Row();
std::string operator[](std::size_t index) const;
void push_back(char *buff, std::size_t length);
const char *get_buffer(std::size_t index, std::size_t &length) const;
std::size_t size_of_element(std::size_t index) const;
bool is_value_null(std::size_t index) const;
std::size_t size() const;
Iterator begin() const;
Iterator end() const;
MYSQL_RES *get_mysql_result_info() const;
class Iterator {
public:
Iterator(const Row &row, std::size_t index);
bool is_value_null();
std::string operator*();
void operator++();
bool operator==(const Iterator &other);
bool operator!=(const Iterator &other);
private:
const Row &m_row;
std::size_t m_index;
};
private:
void reserve(std::size_t strings, std::size_t buffer_size);
// Represents table row as a string
char *m_buffer;
// Represents offsets to each column in m_buffer
std::vector<std::size_t> m_buffer_starts;
// Total buffer size
std::size_t m_buffer_capacity;
// Actual buffer size
std::size_t m_buffer_size;
MYSQL_RES *m_mysql_result_info;
};
private:
/**
Runs specified query and process result rows and messages to callbacks.
Does not check for multiple queries being executed in parallel.
*/
int64 run_query_unguarded(std::string query);
/**
Creates error message from mysql_errno and mysql_error and passes it to
callbacks.
*/
int64 report_mysql_error();
/**
Creates error message from mysql_errno and mysql_error and passes it to
callbacks.
*/
int64 report_message(Message_data &message);
/**
Returns parsed Message_type from given MySQL severity string.
*/
Message_type get_message_type_from_severity(std::string severity);
class Store_result_helper {
public:
Store_result_helper(std::vector<const Row *> *result);
std::function<int64(const Row &)> *get_result_callback();
private:
int64 result_callback(const Row &row);
std::vector<const Row *> *m_result;
};
std::vector<std::function<int64(const Row &)> *> m_result_callbacks;
std::vector<std::pair<std::function<int64(const Message_data &)> *,
std::function<void()>>>
m_message_callbacks;
/**
Indicates if there is query currently executed. Only one query can be
executed in specified time moment.
*/
std::atomic<bool> *m_is_processing;
/**
Indicates if this is original runner or a copy. In case of original the
cleanup is performed on destruction.
*/
bool m_is_original_runner;
MYSQL *m_connection;
};
} // namespace Base
} // namespace Tools
} // namespace Mysql
#endif