Skip to content

Commit 7cbe4ce

Browse files
JavierJFrenecannao
authored andcommitted
Fix regression introduced for 'at signs' parsing for multiplexing disabling (#3647)
* Fixed regression introduced for 'at-signs' parsing and improved implementation * Added minimal test for checking multiplexing disabling via 'mysql-keep_multiplexing_variables' * Added missing 'plan()' to test specifying the number of test cases
1 parent 33ed285 commit 7cbe4ce

File tree

2 files changed

+166
-8
lines changed

2 files changed

+166
-8
lines changed

lib/mysql_connection.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,17 +2293,18 @@ bool MySQL_Connection::IsKeepMultiplexEnabledVariables(char *query_digest_text)
22932293
}
22942294
//filter @@session. and @@
22952295
char *match=NULL;
2296+
char* last_pos=NULL;
2297+
const int at_session_offset = strlen("@@session.");
2298+
const int double_at_offset = strlen("@@");
22962299
while (query_digest_text_filter_select && (match = strcasestr(query_digest_text_filter_select,"@@session."))) {
2297-
*match = '\0';
2298-
strcat(query_digest_text_filter_select, match+strlen("@@session."));
2300+
memmove(match, match + at_session_offset, strlen(match) - at_session_offset);
2301+
last_pos = match + strlen(match) - at_session_offset;
2302+
*last_pos = '\0';
22992303
}
23002304
while (query_digest_text_filter_select && (match = strcasestr(query_digest_text_filter_select,"@@"))) {
2301-
*match = '\0';
2302-
if (strlen(query_digest_text_filter_select) == 0) {
2303-
memcpy(query_digest_text_filter_select, match, strlen("@@"));
2304-
} else {
2305-
strcat(query_digest_text_filter_select, match+strlen("@@"));
2306-
}
2305+
memmove(match, match + double_at_offset, strlen(match) - double_at_offset);
2306+
last_pos = match + strlen(match) - double_at_offset;
2307+
*last_pos = '\0';
23072308
}
23082309

23092310
std::vector<char*>query_digest_text_filter_select_v;
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* @file test_keep_multiplexing_variables-t.cpp
3+
* @brief This test checks that selecting on '@@session.*' and '@@*' variables disables multiplexing when
4+
* target variables are not specified by 'mysql-keep_multiplexing_variables'.
5+
* @date 2021-09-30
6+
*/
7+
8+
#include <vector>
9+
#include <string>
10+
#include <stdio.h>
11+
#include <mysql.h>
12+
13+
#include "tap.h"
14+
#include "command_line.h"
15+
#include "utils.h"
16+
#include "json.hpp"
17+
18+
using std::string;
19+
using namespace nlohmann;
20+
21+
void parse_result_json_column(MYSQL_RES *result, json& j) {
22+
if(!result) return;
23+
MYSQL_ROW row;
24+
25+
while ((row = mysql_fetch_row(result))) {
26+
j = json::parse(row[0]);
27+
}
28+
}
29+
30+
std::vector<std::string> select_queries {
31+
"select @@session.autocommit, @@session.big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@transaction_isolation, @@version,@@session.transaction_isolation",
32+
"select @@autocommit, @@sql_mode, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@session.transaction_isolation, @@version,@@transaction_isolation",
33+
"select @@autocommit, @@sql_mode, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@session.transaction_isolation, @@version,@@transaction_isolation",
34+
"select @@autocommit, @@sql_mode, @@big_tables, @@autocommit,@@session.bulk_insert_buffer_size, @@character_set_database,@@session.transaction_isolation, @@version,@@transaction_isolation",
35+
"select @@sql_mode, @@autocommit, @@big_tables, @@autocommit, @@character_set_database,@@transaction_isolation, @@version,@@session.transaction_isolation",
36+
"select @@sql_mode, @@autocommit, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@transaction_isolation, @@version,@@session.transaction_isolation",
37+
"select @@sql_mode, @@autocommit, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@transaction_isolation, @@version,@@session.transaction_isolation",
38+
"select @@session.autocommit, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@transaction_isolation, @@version,@@session.transaction_isolation",
39+
"select @@big_tables, @@session.autocommit, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@transaction_isolation, @@version,@@session.transaction_isolation",
40+
"select @@session.autocommit, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database, @@version,@@session.transaction_isolation",
41+
"select @@session.autocommit, @@big_tables, @@autocommit,@@bulk_insert_buffer_size, @@character_set_database,@@transaction_isolation, @@version,@@session.transaction_isolation",
42+
};
43+
44+
int check_multiplexing_disabled(const CommandLine& cl, const std::string query, bool& multiplex_disabled) {
45+
MYSQL* proxysql_mysql = mysql_init(NULL);
46+
47+
if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
48+
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql));
49+
return EXIT_FAILURE;
50+
}
51+
52+
MYSQL_QUERY(proxysql_mysql, query.c_str());
53+
MYSQL_RES* dummy_res = mysql_store_result(proxysql_mysql);
54+
mysql_free_result(dummy_res);
55+
56+
MYSQL_QUERY(proxysql_mysql, "PROXYSQL INTERNAL SESSION");
57+
json j_status {};
58+
MYSQL_RES* int_session_res = mysql_store_result(proxysql_mysql);
59+
parse_result_json_column(int_session_res, j_status);
60+
mysql_free_result(int_session_res);
61+
62+
if (j_status.contains("backends")) {
63+
for (auto& backend : j_status["backends"]) {
64+
if (backend != nullptr && backend.contains("conn") && backend["conn"].contains("status")) {
65+
multiplex_disabled = backend["conn"]["MultiplexDisabled"];
66+
}
67+
}
68+
}
69+
70+
mysql_close(proxysql_mysql);
71+
72+
return EXIT_SUCCESS;
73+
}
74+
75+
int main(int argc, char** argv) {
76+
CommandLine cl;
77+
78+
if (cl.getEnv()) {
79+
diag("Failed to get the required environmental variables.");
80+
return EXIT_FAILURE;
81+
}
82+
83+
plan(26);
84+
85+
MYSQL* proxysql_admin = mysql_init(NULL);
86+
87+
if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
88+
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
89+
return EXIT_FAILURE;
90+
}
91+
92+
// Clean the 'keep_multiplexing_variables'
93+
MYSQL_QUERY(proxysql_admin, "SET mysql-keep_multiplexing_variables='version'");
94+
MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME");
95+
diag("Cleaning 'mysql-keep_multiplexing_variables' to check multiplexing disabling.");
96+
97+
// Check that any query will disable multiplexing
98+
{
99+
bool disabled_multiplexing = false;
100+
int check_multiplexing_err = check_multiplexing_disabled(cl, "SELECT @@sql_mode", disabled_multiplexing);
101+
ok (disabled_multiplexing == true, "Simple 'SELECT @@*' should disable multiplexing.");
102+
}
103+
104+
{
105+
bool disabled_multiplexing = false;
106+
int check_multiplexing_err = check_multiplexing_disabled(cl, "SELECT @@SESSION.sql_mode", disabled_multiplexing);
107+
ok (disabled_multiplexing == true, "Simple 'SELECT @@SESSION.*' should disable multiplexing.");
108+
}
109+
110+
// Adding the variable to 'keep_multiplexing_variables' should keep multiplexing enabled
111+
MYSQL_QUERY(proxysql_admin, "SET mysql-keep_multiplexing_variables='version,sql_mode'");
112+
MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME");
113+
diag("Setting 'mysql-keep_multiplexing_variables' to keep multiplexing enabled.");
114+
115+
// Check that any query will disable multiplexing
116+
{
117+
bool disabled_multiplexing = false;
118+
int check_multiplexing_err = check_multiplexing_disabled(cl, "SELECT @@sql_mode", disabled_multiplexing);
119+
ok (disabled_multiplexing == false, "Simple 'SELECT @@*' should keep multiplexing enabled.");
120+
}
121+
122+
{
123+
bool disabled_multiplexing = false;
124+
int check_multiplexing_err = check_multiplexing_disabled(cl, "SELECT @@SESSION.sql_mode", disabled_multiplexing);
125+
ok (disabled_multiplexing == false, "Simple 'SELECT @@SESSION.*' should keep multiplexing enabled.");
126+
}
127+
128+
// Clean the 'keep_multiplexing_variables'
129+
MYSQL_QUERY(proxysql_admin, "SET mysql-keep_multiplexing_variables='version'");
130+
MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME");
131+
diag("Cleaning 'mysql-keep_multiplexing_variables' to check multiplexing disabling.");
132+
133+
{
134+
for (const std::string& query : select_queries) {
135+
bool disabled_multiplexing = true;
136+
int check_multiplexing_err = check_multiplexing_disabled(cl, query, disabled_multiplexing);
137+
ok (disabled_multiplexing == true, "Complex 'SELECT @@SESSION.*, @@*' should disable multiplexing.");
138+
}
139+
}
140+
141+
// Adding multiple variables to 'keep_multiplexing_variables' should keep multiplexing enabled
142+
MYSQL_QUERY(proxysql_admin, "SET mysql-keep_multiplexing_variables='version,sql_mode,autocommit,big_tables,bulk_insert_buffer_size,character_set_database,transaction_isolation'");
143+
MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME");
144+
diag("Setting 'mysql-keep_multiplexing_variables' to keep multiplexing enabled.");
145+
146+
{
147+
for (const std::string& query : select_queries) {
148+
bool disabled_multiplexing = false;
149+
int check_multiplexing_err = check_multiplexing_disabled(cl, query, disabled_multiplexing);
150+
ok (disabled_multiplexing == false, "Complex 'SELECT @@SESSION.*, @@*' queries should keep multiplexing enabled.");
151+
}
152+
}
153+
154+
mysql_close(proxysql_admin);
155+
156+
return exit_status();
157+
}

0 commit comments

Comments
 (0)