Пример использования mysql_cli
в учебниках аналогичен официальному клиенту. Это асинхронный командно-строчный клиент MySQL.
Способ запуска: ./mysql_cli <URL>
После запуска можно вводить команды MySQL прямо в терминале для взаимодействия с базой данных. Для выхода используйте quit
или Ctrl-C
.
mysql://имя_пользователя:пароль@хост:порт/имя_базы?character_set=charset&character_set_results=charset
Если требуется SSL-соединение, схема должна быть установлена как mysqls://. Поддерживается MySQL серверами версии OnClickListener onClick="window.location.href='/docs/about-upstream.md'" version="5.7">5.7 и выше;
имя пользователя и пароль должны быть указаны при необходимости. Если пароль содержит специальные символы, они должны быть экранированы перед добавлением в URL;
// Пароль: @@@@####
std::string url = "mysql://root:" + StringUtil::url_encode_component("@@@@####") + "@127.0.0.1";
порт по умолчанию равен 3306;
имя_базы — это имя базы данных, которую вы хотите использовать. Обычно рекомендуется указывать его, если SQL-запросы оперируют одной базой данных;
если вам необходим выбор upstream, обратитесь к документации по upstream;
character_set представляет собой набор символов клиента, эквивалентный параметру --default-character-set при запуске официального клиента. По умолчанию utf8, подробнее см. MySQL официальную документацию character-set.html.
character_set_results представляет собой набор символов для клиента, соединения и результатов. Если вы хотите использовать SET NAME для указания этих наборов символов внутри SQL-запроса, то следует указать их здесь в URL.
Пример URL MySQL:
mysql://root:пароль@127.0.0.1
mysql://@test.mysql.com:3306/db1?character_set=utf8&character_set_results=utf8
mysqls://localhost/db1?character_set=big5
Пользователи могут создавать задачи MySQL с помощью WFTaskFactory. Интерфейсы создания и вызова обратных функций аналогичны другим задачам workflow:
using mysql_callback_t = std::function<void (WFMySQLTask *)>;
WFMySQLTask *create_mysql_task(const std::string& url, int retry_max, mysql_callback_t callback);
void set_query(const std::string& query);
После создания объекта WFMySQLTask пользователи могут использовать метод set_query() для записи SQL-запросов.
Если метод set_query() не был вызван, но задача была запущена, пользователи получат ошибку WFT_ERR_MYSQL_QUERY_NOT_SET в обратной функции.
Другие элементы, такие как обратные функции, последовательность, данные пользователя и прочее, используются аналогично другим задачам workflow.
Пример использования:
int main(int argc, char *argv[])
{
...
WFMySQLTask *task = WFTaskFactory::create_mysql_task(url, RETRY_MAX, mysql_callback);
task->get_req()->set_query("SHOW TABLES;");
...
task->start();
...
}
На данный момент поддерживаются команды COM_QUERY, что позволяет выполнять основные операции CRUD, создавать и удалять базы данных, таблицы, подготовленные запросы, процедуры и транзакции.
Интерактивные команды не поддерживают выбор базы данных (команда USE), поэтому для выполнения операций через несколько баз данных используется способ указания конкретной базы данных и таблицы в виде db_name.table_name.
Все остальные команды могут быть объединены вместе с использованием set_query()
и переданы WFMySQLTask (например, INSERT/UPDATE/SELECT/DELETE/PREPARE/CALL).
Объединённые команды будут выполняться последовательно до первой ошибки, все предыдущие команды будут успешно выполнены.
Пример:
req->set_query("SELECT * FROM table1; CALL procedure1(); INSERT INTO table3 (id) VALUES (1);");
Аналогично другим задачам workflow, результаты можно получить с помощью task->get_resp()
, который возвращает объект MySQLResponse. Мы можем использовать MySQLResultCursor для прохождения по результатам. Дополнительные интерфейсы доступны в MySQLResult.h.
Ответ на один запрос состоит из трёхмерной структуры данных:
Два типа результатных множеств можно проверять с помощью cursor->get_cursor_status()
.
MYSQL_STATUS_GET_RESULT | MYSQL_STATUS_OK | |
---|---|---|
SQL-запрос | SELECT (включая каждый SELECT в хранимых процедурах) | INSERT / UPDATE / DELETE / ... |
Значение | Чтение, одно множество представляет собой двумерную таблицу | Запись, одно множество показывает успешность операции записи |
Основные интерфейсы | fetch_fields();fetch_row(&row_arr);... | get_insert_id();get_affected_rows();... |
При наличии ошибок в объединённых запросах, можно использовать MySQLResultCursor для получения нескольких результатных множеств, правильно выполненных ранее, а также использовать resp->get_error_code()
и resp->get_error_msg()
для получения информации об ошибке.
Хранимая процедура, содержащая n команд SELECT, будет возвращать n результатных множеств типа MYSQL_STATUS_GET_RESULT и одно множество типа MYSQL_STATUS_OK, которое можно игнорировать.
Основные шаги анализа результатов следуют в порядке:
Проверьте состояние задачи (состояние уровня связи): пользователи могут проверить успех выполнения задачи, сравнивая task->get_state()
с WFT_STATE_SUCCESS;
Проверьте тип пакета ответа (состояние парсинга ответа): используйте resp->get_packet_type() для проверки типа последнего MySQL-запроса. Некоторые распространённые типы:
Поскольку мы работаем с высокопроизводительной асинхронной клиентской частью, это означает, что количество соединений с одним сервером может превышать одно. В то же время операции транзакций и подготовленных запросов в MySQL имеют состояние, поэтому для обеспечения того, чтобы каждая транзакция или подготовленный запрос использовала уникальное соединение, пользователи могут использовать нашу двойную завернутую реализацию WFMySQLConnection. Каждое соединение WFMySQLConnection гарантирует использование одного уникального соединения. Подробнее см. WFMySQLConnection.h.
При создании объекта WFMySQLConnection требуется передать идентификатор, который будет использоваться внутри при вызовах.
Инициализация требует передачи URL, после чего все задачи, созданные на этом соединении, больше не будут нуждаться в указании URL.
class WFMySQLConnection
{
public:
WFMySQLConnection(int id);
int init(const std::string& url);
...
};
Чтобы создать задачу, используйте метод create_query_task()
и передайте SQL-запрос и обратный вызов. Эта задача гарантировано будет отправлена через это конкретное соединение.
Когда соединение больше не используется, его можно закрыть, используя метод create_disconnect_task()
. Это позволит освободить ресурсы.
class WFMySQLConnection
{
public:
...
WFMySQLTask *create_query_task(const std::string& query,
mysql_callback_t callback);
WFMySQLTask *create_disconnect_task(mysql_callback_t callback);
}
Объект WFMySQLConnection работает как двойная завернутая реализация. Мы рекомендуем не хранить объекты завершенных задач, следующий код полностью легален:
WFMySQLConnection *conn = new WFMySQLConnection(1234);
conn->init(url);
auto *task = conn->create_query_task("SELECT * FROM table", my_callback);
conn->deinit();
delete conn;
task->start();
Не следует бесконечно генерировать новые идентификаторы для создания новых соединений, так как каждый идентификатор занимает небольшую область памяти. Когда соединение больше не используется, его можно вернуть внутреннему пулу соединений, вместо того чтобы создавать и запускать задачу отключения.Если несколько задач начинаются параллельно на одном соединении, они могут получить ошибку EAGAIN.
Если во время выполнения транзакции произойдет разрыв соединения до COMMIT или ROLLBACK, соединение будет автоматически восстановлено фреймворком. При следующей попытке запроса пользователю будет выдана ошибка ECONNRESET. Незавершенная транзакция станет недействительной и потребует повторного выполнения.
Пользователи также могут использовать WFMySQLConnection для выполнения предварительной подготовки PREPARE, что позволяет защититься от SQL-инъекций. Если соединение было восстановлено, будет получена ошибка ECONNRESET.
WFMySQLConnection conn(1);
conn.init("mysql://root@127.0.0.1/test");
// тест транзакции
const char *query = "BEGIN;";
WFMySQLTask *t1 = conn.create_query_task(query, task_callback);
query = "SELECT * FROM check_tiny FOR UPDATE;";
WFMySQLTask *t2 = conn.create_query_task(query, task_callback);
query = "INSERT INTO check_tiny VALUES (8);";
WFMySQLTask *t3 = conn.create_query_task(query, task_callback);
query = "COMMIT;";
WFMySQLTask *t4 = conn.create_query_task(query, task_callback);
WFMySQLTask *t5 = conn.create_disconnect_task(task_callback);
((*t1) > t2 > t3 > t4 > t5).start();
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )