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.
proxysql/test/tap/tests/test_session_status_flags-t...

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