mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
781 lines
27 KiB
781 lines
27 KiB
/**
|
|
* @file test_session_status_flags-t.cpp
|
|
* @brief Test file for testing the different operations that modify the 'status_flags' in a MySQL_Session.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <mysql.h>
|
|
#include <mysqld_error.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <unistd.h>
|
|
#include "json.hpp"
|
|
|
|
#include "tap.h"
|
|
#include "utils.h"
|
|
#include "command_line.h"
|
|
|
|
using nlohmann::json;
|
|
|
|
void parse_result_json_column(MYSQL_RES *result, json& j) {
|
|
if(!result) return;
|
|
MYSQL_ROW row;
|
|
|
|
while ((row = mysql_fetch_row(result))) {
|
|
j = json::parse(row[0]);
|
|
}
|
|
}
|
|
|
|
// This test was previously failing due to replication not catching up quickly enough when doing
|
|
// some table creation operations. This variable controls the waiting timeout after these
|
|
// create operations are performed. See #3282 for context.
|
|
constexpr const int replication_timeout = 10;
|
|
|
|
int main(int argc, char *argv[]) {
|
|
CommandLine cl;
|
|
|
|
if(cl.getEnv()) {
|
|
return exit_status();
|
|
}
|
|
|
|
MYSQL* proxysql_admin = mysql_init(NULL);
|
|
if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
|
|
return -1;
|
|
}
|
|
|
|
// Set a replication lag inferior to default one (60). This is to prevent reads
|
|
// from a replica in which replication is currently disabled.
|
|
MYSQL_QUERY(proxysql_admin, "UPDATE mysql_servers SET max_replication_lag=20");
|
|
MYSQL_QUERY(proxysql_admin, "LOAD MYSQL SERVERS TO RUNTIME");
|
|
|
|
// Wait for ProxySQL to detect replication issues
|
|
sleep(10);
|
|
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
// Check that transaction state is reflected when actively in a transaction
|
|
const std::vector<std::string> transaction_queries { "START TRANSACTION", "SELECT 1", "PROXYSQL INTERNAL SESSION", "COMMIT" };
|
|
json j_status;
|
|
|
|
for (const auto& query : transaction_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
int32_t server_status = backend["conn"]["mysql"]["server_status"];
|
|
ok(server_status & 0x01, "Connection status should reflect being in a transaction");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, CLIENT_COMPRESS)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
// Check that state reflects when in a compressed connection
|
|
const std::string internal_session_query { "PROXYSQL INTERNAL SESSION" };
|
|
json j_status;
|
|
|
|
MYSQL_QUERY(proxysql_mysql, internal_session_query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
parse_result_json_column(tr_res, j_status);
|
|
mysql_free_result(tr_res);
|
|
|
|
bool compression_enabled = j_status["conn"]["status"]["compression"];
|
|
ok(compression_enabled == true, "Connection status should reflect being in a compressed connection");
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// USER VARIABLE
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
// Check that state reflects when in a compressed connection
|
|
const std::vector<std::string> user_variable_queries { "SET @test_variable = 43", "PROXYSQL INTERNAL SESSION" };
|
|
json j_status;
|
|
|
|
for (const auto& query : user_variable_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
int32_t user_variable_status = backend["conn"]["status"]["user_variable"];
|
|
ok(user_variable_status == true, "Connection status should reflect that a 'user_variable' have been set.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// PREPARED STATEMENT
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const std::vector<std::string> prepared_stmt_queries { "PREPARE stmt_test FROM 'SELECT 1'", "PROXYSQL INTERNAL SESSION" };
|
|
json j_status;
|
|
|
|
for (const auto& query : prepared_stmt_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool prepared_stmt = backend["conn"]["status"]["prepared_statement"];
|
|
ok(prepared_stmt == true, "Connection status should reflect that a 'prepared statement' have been prepared.");
|
|
|
|
bool multiplex_disabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(multiplex_disabled == true, "Connection status should reflect that 'MultiplexDisabled' is enabled due to the 'prepared statement'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_LOCK_TABLES
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const char* create_test_table =
|
|
"CREATE TABLE IF NOT EXISTS sysbench.test_session_var ("
|
|
" c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
|
|
" c2 VARCHAR(100),"
|
|
" c3 VARCHAR(100)"
|
|
")";
|
|
const std::vector<std::string> prepared_stmt_queries {
|
|
create_test_table,
|
|
"LOCK TABLES sysbench.test_session_var READ",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
// Set a variable so we make sure connection is not dropped after "UNLOCK TABLES"
|
|
"SET @test_variable = 43",
|
|
"UNLOCK TABLES",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
"DROP TABLE sysbench.test_session_var"
|
|
};
|
|
|
|
std::vector<json> vj_status;
|
|
|
|
for (const auto& query : prepared_stmt_queries) {
|
|
json j_status;
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
vj_status.push_back(j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (vj_status[0].contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : vj_status[0]["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool lock_tables = backend["conn"]["status"]["lock_tables"];
|
|
ok(lock_tables == true, "Connection status should reflect that 'LOCK TABLE' have been executed.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
if (vj_status[1].contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : vj_status[1]["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool unlock_tables = backend["conn"]["status"]["lock_tables"];
|
|
ok(unlock_tables == false, "Connection status should reflect that 'UNLOCK TABLE' have been executed.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_TEMPORARY_TABLE
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const char* create_test_table =
|
|
"CREATE TEMPORARY TABLE IF NOT EXISTS sysbench.test_temp_table_session_var ("
|
|
" c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
|
|
" c2 VARCHAR(100),"
|
|
" c3 VARCHAR(100)"
|
|
")";
|
|
const std::vector<std::string> prepared_stmt_queries {
|
|
create_test_table,
|
|
"PROXYSQL INTERNAL SESSION",
|
|
"DROP TABLE sysbench.test_temp_table_session_var"
|
|
};
|
|
json j_status;
|
|
|
|
for (const auto& query : prepared_stmt_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool temp_table = backend["conn"]["status"]["temporary_table"];
|
|
ok(temp_table == true, "Connection status should reflect that a 'CREATE TEMPORARY TABLE' have been executed.");
|
|
|
|
bool multiplex_disabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(multiplex_disabled == true, "Connection status should reflect that 'MultiplexDisabled' is enabled due to 'CREATE TEMPORARY TABLE'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_GET_LOCK
|
|
// TODO: Check why when GET_LOCK is executed the first backend is "NULL", and not filled like in the rest
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const std::vector<std::string> prepared_stmt_queries {
|
|
"SELECT 1",
|
|
"SELECT GET_LOCK('test_session_vars_lock', 2)",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
"SELECT RELEASE_LOCK('test_session_vars_lock')"
|
|
};
|
|
json j_status;
|
|
|
|
for (const auto& query : prepared_stmt_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool lock_tables = backend["conn"]["status"]["get_lock"];
|
|
ok(lock_tables == true, "Connection status should reflect that a 'GET_LOCK' have been executed.");
|
|
|
|
bool multiplex_disabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(multiplex_disabled == true, "Connection status should reflect that 'MultiplexDisabled' is enabled due to 'GET_LOCK'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_NO_MULTIPLEX - SET VARIABLE
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const std::vector<std::string> prepared_stmt_queries {
|
|
"SET @test_variable = 44",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
};
|
|
json j_status;
|
|
|
|
for (const auto& query : prepared_stmt_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool user_variable = backend["conn"]["status"]["user_variable"];
|
|
ok(user_variable == true, "Connection status should have 'status.user_variable' set due to 'SET @variable'.");
|
|
|
|
bool no_multiplex = backend["conn"]["status"]["no_multiplex"];
|
|
ok(no_multiplex == true, "Connection status should have 'no_multiplex' set due to 'SET @variable'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_NO_MULTIPLEX - TRANSACTION SHOULD NOT REPORT DISABLED MULTIPLEXING
|
|
|
|
// Transaction detection is done through server status, while the MULTIPLEXING will be disabled for the connection and
|
|
// the connection wont be returned to the connection pool, both of the metrics 'MultiplexDisabled' and 'status.no_multiplex'
|
|
// will report 'false'.
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const std::vector<std::string> transaction_queries { "START TRANSACTION", "SELECT 1", "PROXYSQL INTERNAL SESSION", "COMMIT" };
|
|
json j_status;
|
|
|
|
for (const auto& query : transaction_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool MultiplexDisabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(MultiplexDisabled == false, "Connection status should have 'MultiplexDisabled' set to false even with 'START TRANSACTION'.");
|
|
|
|
bool no_multiplex = backend["conn"]["status"]["no_multiplex"];
|
|
ok(no_multiplex == false, "Connection status should have 'no_multiplex' set to false even with 'START TRANSACTION'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_NO_MULTIPLEX - Multiplex disabled due to STATUS_MYSQL_CONNECTION_LOCK_TABLES
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const char* create_test_table =
|
|
"CREATE TABLE IF NOT EXISTS sysbench.test_session_var ("
|
|
" c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
|
|
" c2 VARCHAR(100),"
|
|
" c3 VARCHAR(100)"
|
|
")";
|
|
|
|
const std::vector<std::string> lock_tables_queries {
|
|
create_test_table,
|
|
"LOCK TABLES sysbench.test_session_var READ",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
"UNLOCK TABLES",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
"DROP TABLE sysbench.test_session_var"
|
|
};
|
|
|
|
std::vector<json> vj_status;
|
|
|
|
for (const auto& query : lock_tables_queries) {
|
|
json j_status;
|
|
|
|
// we are trying to lock new created table 'sysbench.test_session_var'
|
|
if (query == lock_tables_queries[1]) {
|
|
int timeout = 0;
|
|
int query_err = 0;
|
|
int query_errno = 0;
|
|
|
|
diag("Executing the locking table query with retrying due to replication lag.");
|
|
|
|
while (timeout < replication_timeout) {
|
|
query_err = mysql_query(proxysql_mysql, query.c_str());
|
|
if (query_err) {
|
|
query_errno = mysql_errno(proxysql_mysql);
|
|
if (query_errno != ER_NO_SUCH_TABLE) {
|
|
break;
|
|
} else {
|
|
sleep(1);
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
timeout++;
|
|
}
|
|
|
|
if (query_err) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
} else {
|
|
diag("Replication lag took '%d.'", timeout);
|
|
}
|
|
} else {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
vj_status.push_back(j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
}
|
|
|
|
if (vj_status[0].contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : vj_status[0]["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool MultiplexDisabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(MultiplexDisabled == true, "Connection status should have 'MultiplexDisabled' set to 'true' 'DUE TO 'LOCK TABLES'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
if (vj_status[1].contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : vj_status[1]["backends"]) {
|
|
if (backend != nullptr) {
|
|
found_backend = true;
|
|
ok(backend.contains("conn") == false, "Connection should be returned to the connection pool due to 'UNLOCK TABLES'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_SQL_LOG_BIN0 - Multiplex disabled due to STATUS_MYSQL_CONNECTION_SQL_LOG_BIN0
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const std::vector<std::string> sql_log_bin_queries {
|
|
"SET SQL_LOG_BIN=0",
|
|
"SELECT 1",
|
|
"PROXYSQL INTERNAL SESSION"
|
|
};
|
|
|
|
json j_status;
|
|
|
|
for (const auto& query : sql_log_bin_queries) {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool MultiplexDisabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(MultiplexDisabled == true, "Connection status should have 'MultiplexDisabled' set to 'true' 'DUE TO 'SET SQL_LOG_BIN'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_FOUND_ROWS - Multiplex disabled due to STATUS_MYSQL_CONNECTION_FOUND_ROWS
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const char* create_test_table =
|
|
"CREATE TABLE IF NOT EXISTS sysbench.test_session_var ("
|
|
" c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
|
|
" c2 VARCHAR(100),"
|
|
" c3 VARCHAR(100)"
|
|
")";
|
|
|
|
const std::vector<std::string> found_rows {
|
|
create_test_table,
|
|
"SELECT SQL_CALC_FOUND_ROWS * from sysbench.test_session_var",
|
|
"SELECT FOUND_ROWS()",
|
|
"PROXYSQL INTERNAL SESSION"
|
|
};
|
|
|
|
json j_status;
|
|
|
|
for (const auto& query : found_rows) {
|
|
// we are trying to 'SELECT' over new created table 'sysbench.test_session_var'
|
|
if (query == found_rows[1]) {
|
|
int timeout = 0;
|
|
int query_err = 0;
|
|
int query_errno = 0;
|
|
|
|
diag("Executing 'SELECT' with retrying due to replication lag.");
|
|
|
|
while (timeout < replication_timeout) {
|
|
query_err = mysql_query(proxysql_mysql, query.c_str());
|
|
if (query_err) {
|
|
query_errno = mysql_errno(proxysql_mysql);
|
|
if (query_errno != ER_NO_SUCH_TABLE) {
|
|
break;
|
|
} else {
|
|
sleep(1);
|
|
}
|
|
} else {
|
|
// free select results
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
mysql_free_result(tr_res);
|
|
break;
|
|
}
|
|
timeout++;
|
|
}
|
|
|
|
if (query_err) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
} else {
|
|
diag("Replication lag took '%d.'", timeout);
|
|
}
|
|
} else {
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
}
|
|
|
|
if (j_status.contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : j_status["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool found_rows = backend["conn"]["status"]["found_rows"];
|
|
ok(found_rows == true, "Connection status should have 'status.found_rows' set to 'true' 'DUE TO 'SQL_CALC_FOUND_ROWS'.");
|
|
|
|
bool MultiplexDisabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(MultiplexDisabled == true, "Connection status should have 'MultiplexDisabled' set to 'true' 'DUE TO 'SQL_CALC_FOUND_ROWS'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
// STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT - Multiplex disabled due to STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT
|
|
{
|
|
MYSQL* proxysql_mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
|
|
return -1;
|
|
}
|
|
|
|
const std::vector<std::string> savepoint_queries {
|
|
"SET AUTOCOMMIT=0",
|
|
"SAVEPOINT test_session_variables_savepoint",
|
|
"PROXYSQL INTERNAL SESSION",
|
|
"COMMIT",
|
|
"PROXYSQL INTERNAL SESSION"
|
|
};
|
|
|
|
std::vector<json> vj_status;
|
|
|
|
for (const auto& query : savepoint_queries) {
|
|
json j_status;
|
|
MYSQL_QUERY(proxysql_mysql, query.c_str());
|
|
MYSQL_RES* tr_res = mysql_store_result(proxysql_mysql);
|
|
if (query == "PROXYSQL INTERNAL SESSION") {
|
|
parse_result_json_column(tr_res, j_status);
|
|
vj_status.push_back(j_status);
|
|
}
|
|
mysql_free_result(tr_res);
|
|
}
|
|
|
|
if (vj_status[0].contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : vj_status[0]["backends"]) {
|
|
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
|
|
found_backend = true;
|
|
bool found_rows = backend["conn"]["status"]["has_savepoint"];
|
|
ok(found_rows == true, "Connection status should have 'status.has_savepoint' set to 'true' 'DUE TO 'SAVEPOINT'.");
|
|
|
|
bool MultiplexDisabled = backend["conn"]["MultiplexDisabled"];
|
|
ok(MultiplexDisabled == true, "Connection status should have 'MultiplexDisabled' set to 'true' 'DUE TO 'SAVEPOINT'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
if (vj_status[1].contains("backends")) {
|
|
bool found_backend = false;
|
|
for (const auto& backend : vj_status[1]["backends"]) {
|
|
if (backend != nullptr) {
|
|
found_backend = true;
|
|
ok(backend.contains("conn") == false, "Connection should be returned to the connection pool due to 'COMMIT'.");
|
|
}
|
|
}
|
|
if (found_backend == false) {
|
|
ok(false, "'backends' doens't contains 'conn' objects with the relevant session information");
|
|
}
|
|
} else {
|
|
ok(false, "No backends detected for the current connection.");
|
|
}
|
|
|
|
mysql_close(proxysql_mysql);
|
|
}
|
|
|
|
mysql_close(proxysql_admin);
|
|
|
|
return exit_status();
|
|
}
|