mirror of https://github.com/sysown/proxysql
Deprecated variables: - net_write_timeout Renamed set_testing-t.csv to set_testing-t.csv.obsolete , and removed net_write_timeout from set_testing-t.csv Variables added to ignore list: - net_write_timeout - net_buffer_length - read_buffer_size - read_rnd_buffer_size Added support for quoting with backtick Renamed `enum variable_name` into `enum mysql_variable_name` for better readibility `enum mysql_variable_name` has variable names alphabetically ordered after SQL_NAME_LAST_LOW_WM `mysql_tracked_variables` has variable names alphabetically ordered after SQL_NAME_LAST_LOW_WM A lot of new variables added in `mysql_tracked_variables` , although not all tracked yet (TODO) In `MySQL_Variables::MySQL_Variables()`: - if `internal_variable_name` in `mysql_tracked_variables` is NULL , it will be automatically initialized - it performs some sanity check between `enum mysql_variable_name` and `mysql_tracked_variables` Testing: - refactored code in set_testing-t.cpp and set_testing-multi-t.cpp - added set_testing-240-t.cpp to test improvements in 2.4.0 - generate_set_session_csv to automatically create set_testing-240.csv used by set_testing-240-tpull/3702/head
parent
189b30b630
commit
d335bfb899
@ -0,0 +1,410 @@
|
||||
/**
|
||||
* @file set_testing-t.cpp
|
||||
* @brief This file tests multiple settings combinations for MySQL variables, and checks that they are
|
||||
* actually being tracked correctly.
|
||||
* @details The test input is a 'csv' file with name 'set_testing-t.csv'. The file format consists in
|
||||
* two primary columns which specifies the variables to set (first) and the expected result of setting
|
||||
* those variables (second), and an optional third column which hold variables that shouldn't be checked
|
||||
* anymore after the 'SET STATEMENTS' from the same line are executed.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <mysql.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
|
||||
#include "json.hpp"
|
||||
#include "re2/re2.h"
|
||||
#include "re2/regexp.h"
|
||||
|
||||
#include "tap.h"
|
||||
#include "utils.h"
|
||||
#include "command_line.h"
|
||||
|
||||
|
||||
|
||||
int queries_per_connections=1;
|
||||
unsigned int num_threads=1;
|
||||
int count=0;
|
||||
char *username=NULL;
|
||||
char *password=NULL;
|
||||
char *host=(char *)"localhost";
|
||||
int port=3306;
|
||||
int multiport=1;
|
||||
char *schema=(char *)"information_schema";
|
||||
int silent = 0;
|
||||
int sysbench = 0;
|
||||
int local=0;
|
||||
int queries=0;
|
||||
int uniquequeries=0;
|
||||
int histograms=-1;
|
||||
|
||||
bool is_mariadb = false;
|
||||
bool is_cluster = false;
|
||||
unsigned int g_connect_OK=0;
|
||||
unsigned int g_connect_ERR=0;
|
||||
unsigned int g_select_OK=0;
|
||||
unsigned int g_select_ERR=0;
|
||||
|
||||
unsigned int g_passed=0;
|
||||
unsigned int g_failed=0;
|
||||
|
||||
unsigned int status_connections = 0;
|
||||
unsigned int connect_phase_completed = 0;
|
||||
unsigned int query_phase_completed = 0;
|
||||
|
||||
__thread int g_seed;
|
||||
std::mutex mtx_;
|
||||
|
||||
std::vector<std::string> forgotten_vars {};
|
||||
|
||||
#include "set_testing.h"
|
||||
|
||||
|
||||
/* TODO
|
||||
add support for variables with values out of range,
|
||||
for example setting auto_increment_increment to 100000
|
||||
*/
|
||||
|
||||
void * my_conn_thread(void *arg) {
|
||||
g_seed = time(NULL) ^ getpid() ^ pthread_self();
|
||||
unsigned int select_OK=0;
|
||||
unsigned int select_ERR=0;
|
||||
int i, j;
|
||||
MYSQL **mysqlconns=(MYSQL **)malloc(sizeof(MYSQL *)*count);
|
||||
std::vector<json> varsperconn(count);
|
||||
|
||||
if (mysqlconns==NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
std::vector<std::string> cs = {"latin1", "utf8", "utf8mb4", "latin2", "latin7"};
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
MYSQL *mysql=mysql_init(NULL);
|
||||
std::string nextcs = cs[i%cs.size()];
|
||||
|
||||
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, nextcs.c_str());
|
||||
if (mysql==NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
MYSQL *rc=mysql_real_connect(mysql, host, username, password, schema, (local ? 0 : ( port + rand()%multiport ) ), NULL, 0);
|
||||
if (rc==NULL) {
|
||||
if (silent==0) {
|
||||
fprintf(stderr,"%s\n", mysql_error(mysql));
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
mysqlconns[i]=mysql;
|
||||
__sync_add_and_fetch(&status_connections,1);
|
||||
}
|
||||
__sync_fetch_and_add(&connect_phase_completed,1);
|
||||
|
||||
while(__sync_fetch_and_add(&connect_phase_completed,0) != num_threads) {
|
||||
}
|
||||
MYSQL *mysql=NULL;
|
||||
json vars;
|
||||
std::string paddress = "";
|
||||
for (j=0; j<queries; j++) {
|
||||
int fr = fastrand();
|
||||
int r1=fr%count;
|
||||
//int r2=fastrand()%testCases.size();
|
||||
int r2=rand()%testCases.size();
|
||||
|
||||
if (j%queries_per_connections==0) {
|
||||
mysql=mysqlconns[r1];
|
||||
vars = varsperconn[r1];
|
||||
}
|
||||
if (strcmp(username,(char *)"root")) {
|
||||
if (strstr(testCases[r2].command.c_str(),"database")) {
|
||||
std::lock_guard<std::mutex> lock(mtx_);
|
||||
skip(1, "connections mysql[%p] proxysql[%s], command [%s]", mysql, paddress.c_str(), testCases[r2].command.c_str());
|
||||
continue;
|
||||
}
|
||||
if (strstr(testCases[r2].command.c_str(),"sql_log_bin")) {
|
||||
std::lock_guard<std::mutex> lock(mtx_);
|
||||
skip(1, "connections: mysql[%p] proxysql[%s], command [%s]", mysql, paddress.c_str(), testCases[r2].command.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
diag("Thread_id: %lu, random number: %d . Query/ies: %s", mysql->thread_id, r2, testCases[r2].command.c_str());
|
||||
std::vector<std::string> commands = split(testCases[r2].command.c_str(), ';');
|
||||
for (auto c : commands) {
|
||||
if (mysql_query(mysql, c.c_str())) {
|
||||
if (silent==0) {
|
||||
fprintf(stderr,"ERROR while running -- \"%s\" : (%d) %s\n", c.c_str(), mysql_errno(mysql), mysql_error(mysql));
|
||||
}
|
||||
} else {
|
||||
MYSQL_RES *result = mysql_store_result(mysql);
|
||||
mysql_free_result(result);
|
||||
select_OK++;
|
||||
__sync_fetch_and_add(&g_select_OK,1);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& el : testCases[r2].expected_vars.items()) {
|
||||
if (el.key() == "transaction_isolation") {
|
||||
if (is_mariadb) {
|
||||
vars["tx_isolation"] = el.value();
|
||||
}
|
||||
else {
|
||||
vars[el.key()] = el.value();
|
||||
}
|
||||
}
|
||||
else if (el.key() == "session_track_gtids") {
|
||||
if (!is_mariadb) {
|
||||
vars[el.key()] = el.value();
|
||||
}
|
||||
}
|
||||
else if (el.key() == "wsrep_sync_wait") {
|
||||
if (is_cluster) {
|
||||
vars[el.key()] = el.value();
|
||||
}
|
||||
}
|
||||
else if (el.key() == "transaction_read_only") {
|
||||
if (is_mariadb) {
|
||||
vars["tx_read_only"] = el.value();
|
||||
} else {
|
||||
vars[el.key()] = el.value();
|
||||
}
|
||||
}
|
||||
else {
|
||||
vars[el.key()] = el.value();
|
||||
}
|
||||
}
|
||||
|
||||
int sleepDelay = fastrand()%100;
|
||||
usleep(sleepDelay * 1000);
|
||||
|
||||
char query[128];
|
||||
sprintf(query, "SELECT /* %p %s */ %d;", mysql, paddress.c_str(), sleepDelay);
|
||||
if (mysql_query(mysql,query)) {
|
||||
select_ERR++;
|
||||
__sync_fetch_and_add(&g_select_ERR,1);
|
||||
} else {
|
||||
MYSQL_RES *result = mysql_store_result(mysql);
|
||||
mysql_free_result(result);
|
||||
select_OK++;
|
||||
__sync_fetch_and_add(&g_select_OK,1);
|
||||
}
|
||||
|
||||
json mysql_vars;
|
||||
queryVariables(mysql, mysql_vars, paddress);
|
||||
|
||||
json proxysql_vars;
|
||||
queryInternalStatus(mysql, proxysql_vars, paddress);
|
||||
|
||||
//diag("MySQL vars: %lu , ProxySQL vars: %lu" , mysql_vars.size(), proxysql_vars.size());
|
||||
|
||||
if (!testCases[r2].reset_vars.empty()) {
|
||||
for (const auto& var : testCases[r2].reset_vars) {
|
||||
if (std::find(forgotten_vars.begin(), forgotten_vars.end(), var) == forgotten_vars.end()) {
|
||||
forgotten_vars.push_back(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool testPassed = true;
|
||||
int variables_tested = 0;
|
||||
for (auto& el : vars.items()) {
|
||||
auto k = mysql_vars.find(el.key());
|
||||
auto s = proxysql_vars["conn"].find(el.key());
|
||||
|
||||
if (std::find(forgotten_vars.begin(), forgotten_vars.end(), el.key()) != forgotten_vars.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k == mysql_vars.end())
|
||||
fprintf(stderr, "Variable %s->%s in mysql resultset was not found.\nmysql data : %s\nproxysql data: %s\ncsv data %s\n",
|
||||
el.value().dump().c_str(), el.key().c_str(), mysql_vars.dump().c_str(), proxysql_vars.dump().c_str(), vars.dump().c_str());
|
||||
|
||||
if (s == proxysql_vars["conn"].end())
|
||||
fprintf(stderr, "Variable %s->%s in proxysql resultset was not found.\nmysql data : %s\nproxysql data: %s\ncsv data %s\n",
|
||||
el.value().dump().c_str(), el.key().c_str(), mysql_vars.dump().c_str(), proxysql_vars.dump().c_str(), vars.dump().c_str());
|
||||
|
||||
bool verified_special_sqlmode = false;
|
||||
bool special_sqlmode = false;
|
||||
|
||||
if (el.key() == "sql_mode") {
|
||||
if (!el.value().is_string()) {
|
||||
diag("Invalid value for 'sql_mode' found. Provided value should be of 'string' type");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (k.value() != el.value()) { // different in mysql
|
||||
std::string e_val { el.value() };
|
||||
std::string k_val { k.value() };
|
||||
std::string s_val { s.value() };
|
||||
if (el.value() == s.value()) { // but same in proxysql
|
||||
std::string str_val { el.value() };
|
||||
if (strcasecmp(str_val.c_str(), "TRADITIONAL")==0) {
|
||||
if (k.value() == "STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION") {
|
||||
special_sqlmode = true;
|
||||
verified_special_sqlmode = true;
|
||||
}
|
||||
} else {
|
||||
if (strcasestr(e_val.c_str(), "sql_mode") != NULL) {
|
||||
// simplified
|
||||
special_sqlmode = true;
|
||||
verified_special_sqlmode = true;
|
||||
}
|
||||
/*
|
||||
re2::RE2::Options options(RE2::Quiet);
|
||||
options.set_case_sensitive(false);
|
||||
options.set_longest_match(false);
|
||||
re2::RE2 concat_re("^CONCAT\\((|@@|@@session\\.)SQL_MODE,\"(.*)\"\\)", options);
|
||||
re2::StringPiece sp_input(str_val);
|
||||
|
||||
std::string f_match {};
|
||||
std::string s_match {};
|
||||
|
||||
re2::RE2::Consume(&sp_input, concat_re, &f_match, &s_match);
|
||||
|
||||
if (!s_match.empty()) {
|
||||
special_sqlmode = true;
|
||||
|
||||
// remove the initial 'comma' if exists
|
||||
if (s_match[0] == ',') {
|
||||
s_match = s_match.substr(1, std::string::npos);
|
||||
}
|
||||
|
||||
std::string k_str_val { k.value() };
|
||||
verified_special_sqlmode =
|
||||
strcasestr(k_str_val.c_str(), s_match.c_str()) != NULL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(special_sqlmode == true && verified_special_sqlmode == false) ||
|
||||
(k == mysql_vars.end()) ||
|
||||
(s == proxysql_vars["conn"].end()) ||
|
||||
(special_sqlmode == false &&
|
||||
(el.key() != "session_track_gtids" && (k.value() != el.value() || s.value() != el.value())) ||
|
||||
(el.key() == "session_track_gtids" && !check_session_track_gtids(el.value(), s.value(), k.value()))
|
||||
)
|
||||
) {
|
||||
if (el.key() == "wsrep_sync_wait" && k == mysql_vars.end() && (s.value() == el.value())) {
|
||||
variables_tested++;
|
||||
} else {
|
||||
__sync_fetch_and_add(&g_failed, 1);
|
||||
testPassed = false;
|
||||
fprintf(stderr, "Test failed for this case %s->%s.\n\nmysql data [%lu]: %s\n\n proxysql data [%lu]: %s\n\n csv data %s\n\n\n",
|
||||
el.value().dump().c_str(), el.key().c_str(),
|
||||
mysql_vars.size(), mysql_vars.dump().c_str(),
|
||||
proxysql_vars.size(), proxysql_vars.dump().c_str(),
|
||||
vars.dump().c_str());
|
||||
diag("FAILED FOR: connections mysql[%p] proxysql[%s], thread_id [%lu], command [%s]", mysql, paddress.c_str(), mysql->thread_id, testCases[r2].command.c_str());
|
||||
//ok(testPassed, "connections mysql[%p] proxysql[%s], thread_id [%lu], command [%s]", mysql, paddress.c_str(), mysql->thread_id, testCases[r2].command.c_str());
|
||||
// In case of failing test, exit completely.
|
||||
//exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
variables_tested++;
|
||||
}
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx_);
|
||||
ok(testPassed, "connections mysql[%p] proxysql[%s], thread_id [%lu], variables_tested [%d], command [%s]", mysql, paddress.c_str(), mysql->thread_id, variables_tested, testCases[r2].command.c_str());
|
||||
}
|
||||
}
|
||||
__sync_fetch_and_add(&query_phase_completed,1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CommandLine cl;
|
||||
|
||||
if(cl.getEnv()) {
|
||||
diag("Failed to get the required environmental variables.");
|
||||
return exit_status();
|
||||
}
|
||||
|
||||
std::string fileName2(std::string(cl.workdir) + "/set_testing-240.csv");
|
||||
|
||||
MYSQL* mysql = mysql_init(NULL);
|
||||
if (!mysql)
|
||||
return exit_status();
|
||||
if (!mysql_real_connect(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(mysql));
|
||||
return exit_status();
|
||||
}
|
||||
MYSQL_QUERY(mysql, "select @@version");
|
||||
MYSQL_RES *result = mysql_store_result(mysql);
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
if (strstr(row[0], "Maria")) {
|
||||
is_mariadb = true;
|
||||
}
|
||||
else {
|
||||
is_mariadb = false;
|
||||
}
|
||||
|
||||
char* first_dash = strstr(row[0], "-");
|
||||
if (!first_dash || !strstr(first_dash+1, "-")) {
|
||||
is_cluster = false;
|
||||
} else {
|
||||
// FIXME: we need a better version detection
|
||||
is_cluster = true;
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
mysql_close(mysql);
|
||||
|
||||
num_threads = 10;
|
||||
queries_per_connections = 10;
|
||||
count = 10;
|
||||
username = cl.username;
|
||||
password = cl.password;
|
||||
host = cl.host;
|
||||
port = cl.port;
|
||||
|
||||
if (!readTestCasesJSON(fileName2)) {
|
||||
fprintf(stderr, "Cannot read %s\n", fileName2.c_str());
|
||||
return exit_status();
|
||||
}
|
||||
queries = 1500;
|
||||
//queries = testCases.size();
|
||||
plan(queries * num_threads);
|
||||
|
||||
if (strcmp(host,"localhost")==0) {
|
||||
local = 1;
|
||||
}
|
||||
if (uniquequeries == 0) {
|
||||
if (queries) uniquequeries=queries;
|
||||
}
|
||||
if (uniquequeries) {
|
||||
uniquequeries=(int)sqrt(uniquequeries);
|
||||
}
|
||||
|
||||
pthread_t *thi=(pthread_t *)malloc(sizeof(pthread_t)*num_threads);
|
||||
if (thi==NULL)
|
||||
return exit_status();
|
||||
|
||||
for (unsigned int i=0; i<num_threads; i++) {
|
||||
if ( pthread_create(&thi[i], NULL, my_conn_thread , NULL) != 0 )
|
||||
perror("Thread creation");
|
||||
}
|
||||
for (unsigned int i=0; i<num_threads; i++) {
|
||||
pthread_join(thi[i], NULL);
|
||||
}
|
||||
return exit_status();
|
||||
}
|
||||
|
Can't render this file because it has a wrong number of fields in line 6.
|
@ -0,0 +1,102 @@
|
||||
"set character_set_results=null; set names latin7; set character_set_client='utf8mb4';", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'utf8mb4'}"
|
||||
"set names latin2", "{'character_set_results':'latin2', 'collation_connection':'latin2_general_ci', 'character_set_connection':'latin2', 'character_set_client':'latin2'}"
|
||||
"set names utf8mb4", "{'character_set_results':'utf8mb4', 'collation_connection':'utf8mb4_general_ci', 'character_set_connection':'utf8mb4', 'character_set_client':'utf8mb4'}"
|
||||
"set character_set_client='utf8mb4'; set names utf8; set character_set_connection='latin1';", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'utf8'}"
|
||||
"set character_set_database='latin1'; set character_set_connection='utf8mb4'; set names utf8; set character_set_client='latin1';", "{'character_set_database':'latin1', 'character_set_results':'utf8', 'collation_connection':'utf8_general_ci', 'character_set_connection':'utf8', 'character_set_client':'latin1'}"
|
||||
"set character_set_connection='utf8mb4'; set names utf8; set character_set_client='latin1'; set collation_connection='latin1_swedish_ci';", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'latin1'}""set names latin7", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'latin7'}"
|
||||
"set collation_connection='utf8mb4_general_ci'; ", "{'collation_connection':'utf8mb4_general_ci', 'character_set_connection':'utf8mb4'}"
|
||||
"set collation_connection='latin1_danish_ci'; ", "{'collation_connection':'latin1_danish_ci', 'character_set_connection':'latin1'}"
|
||||
"set collation_connection='latin1_swedish_ci'", "{'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1'}"
|
||||
"set collation_connection='utf8_general_ci'", "{'collation_connection':'utf8_general_ci', 'character_set_connection':'utf8'}"
|
||||
"SET collation_connection='latin1_swedish_ci'", "{'character_set_connection':'latin1', 'collation_connection':'latin1_swedish_ci'}"
|
||||
"SET collation_connection='utf8_general_ci'", "{'character_set_connection':'utf8', 'collation_connection':'utf8_general_ci'}"
|
||||
"SET collation_connection='utf8mb4_general_ci'", "{'character_set_connection':'utf8mb4', 'collation_connection':'utf8mb4_general_ci'}"
|
||||
"SET character_set_connection='latin1'", "{'character_set_connection':'latin1', 'collation_connection':'latin1_swedish_ci'}"
|
||||
"SET character_set_connection='utf8'", "{'character_set_connection':'utf8', 'collation_connection':'utf8_general_ci'}"
|
||||
"SET character_set_connection='utf8mb4'", "{'character_set_connection':'utf8mb4', 'collation_connection':'utf8mb4_general_ci'}"
|
||||
"SET character_set_results='latin1'", "{'character_set_results':'latin1'}"
|
||||
"SET character_set_results='binary'", "{'character_set_results':'binary'}"
|
||||
"SET character_set_results=NULL", "{'character_set_results':''}"
|
||||
"SET character_set_results='utf8'", "{'character_set_results':'utf8'}"
|
||||
"SET character_set_results='utf8mb4'", "{'character_set_results':'utf8mb4'}"
|
||||
"SET character_set_client='latin1'", "{'character_set_client':'latin1'}"
|
||||
"SET character_set_client='utf8'", "{'character_set_client':'utf8'}"
|
||||
"SET character_set_client='utf8mb4'", "{'character_set_client':'utf8mb4'}"
|
||||
"SET character_set_database='latin1'; ", "{'character_set_database':'latin1'}"
|
||||
"SET character_set_database='utf8'", "{'character_set_database':'utf8'}"
|
||||
"SET character_set_database='utf8mb4'", "{'character_set_database':'utf8mb4'}"
|
||||
"SET sql_log_bin=1", "{'sql_log_bin':'ON'}"
|
||||
"SET sql_log_bin=0", "{'sql_log_bin':'OFF'}"
|
||||
"set sql_mode=''","{'sql_mode':''}"
|
||||
"SET sql_mode='PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'", "{'sql_mode':'PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'}"
|
||||
"SET time_zone='+01:00'","{'time_zone':'+01:00'}"
|
||||
"SET time_zone='-03:00', sql_mode='ALLOW_INVALID_DATES'","{'time_zone':'-03:00', 'sql_mode':'ALLOW_INVALID_DATES'}"
|
||||
"SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION'", "{'time_zone':'+04:00','sql_mode':'NO_ENGINE_SUBSTITUTION'}"
|
||||
"SET sql_safe_updates='OFF'", "{'sql_safe_updates':'OFF'}"
|
||||
"SET sql_safe_updates='ON'", "{'sql_safe_updates':'ON'}"
|
||||
"SET sql_safe_updates=0", "{'sql_safe_updates':'OFF'}"
|
||||
"SET sql_safe_updates=1", "{'sql_safe_updates':'ON'}"
|
||||
"SET sql_select_limit=1010", "{'sql_select_limit':'1010'}"
|
||||
"SET sql_select_limit=2020", "{'sql_select_limit':'2020'}"
|
||||
"SET sql_select_limit=3030", "{'sql_select_limit':'3030'}"
|
||||
"SET time_zone='+01:00'; ","{'time_zone':'+01:00'}"
|
||||
"SET time_zone='-03:00', sql_mode='ALLOW_INVALID_DATES'; ","{'time_zone':'-03:00', 'sql_mode':'ALLOW_INVALID_DATES'}"
|
||||
"SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION'; ", "{'time_zone':'+04:00','sql_mode':'NO_ENGINE_SUBSTITUTION'}"
|
||||
"SET sql_safe_updates='OFF'; ", "{'sql_safe_updates':'OFF'}"
|
||||
"SET sql_safe_updates='ON'; ", "{'sql_safe_updates':'ON'}"
|
||||
"SET sql_safe_updates=0; ", "{'sql_safe_updates':'OFF'}"
|
||||
"SET sql_safe_updates=1; ", "{'sql_safe_updates':'ON'}"
|
||||
"SET sql_select_limit=1010; ", "{'sql_select_limit':'1010'}"
|
||||
"SET sql_select_limit=2020; ", "{'sql_select_limit':'2020'}"
|
||||
"SET sql_select_limit=3030; ", "{'sql_select_limit':'3030'}"
|
||||
"SET session transaction read only", "{'transaction_read_only':'ON'}"
|
||||
"SET session transaction read write", "{'transaction_read_only':'OFF'}"
|
||||
"SET session transaction isolation level READ COMMITTED", "{'transaction_isolation':'READ-COMMITTED'}"
|
||||
"SET session transaction isolation level READ UNCOMMITTED", "{'transaction_isolation':'READ-UNCOMMITTED'}"
|
||||
"SET session transaction isolation level REPEATABLE READ", "{'transaction_isolation':'REPEATABLE-READ'}"
|
||||
"SET session transaction isolation level SERIALIZABLE", "{'transaction_isolation':'SERIALIZABLE'}"
|
||||
"SET tx_isolation='READ-COMMITTED'", "{'transaction_isolation':'READ-COMMITTED'}"
|
||||
"SET tx_isolation='READ-UNCOMMITTED'", "{'transaction_isolation':'READ-UNCOMMITTED'}"
|
||||
"SET tx_isolation='REPEATABLE-READ'", "{'transaction_isolation':'REPEATABLE-READ'}"
|
||||
"SET tx_isolation='SERIALIZABLE'", "{'transaction_isolation':'SERIALIZABLE'}"
|
||||
"SET session_track_gtids=OFF", "{'session_track_gtids':'OFF'}"
|
||||
"SET session_track_gtids=OWN_GTID", "{'session_track_gtids':'OWN_GTID'}"
|
||||
"SET sql_auto_is_null=OFF", "{'sql_auto_is_null':'OFF'}"
|
||||
"SET sql_auto_is_null=ON", "{'sql_auto_is_null':'ON'}"
|
||||
"set net_write_timeout=30", "{'net_write_timeout':'30'}"
|
||||
"set net_write_timeout=60", "{'net_write_timeout':'60'}"
|
||||
"set net_write_timeout=90", "{'net_write_timeout':'90'}"
|
||||
"set max_join_size=20000", "{'max_join_size':'20000'}"
|
||||
"set max_join_size=10000", "{'max_join_size':'10000'}"
|
||||
"set max_join_size=18446744073709551615", "{'max_join_size':'18446744073709551615'}"
|
||||
"set wsrep_sync_wait=1", "{'wsrep_sync_wait':'1'}"
|
||||
"set wsrep_sync_wait=0", "{'wsrep_sync_wait':'0'}"
|
||||
"set group_concat_max_len=2048", "{'group_concat_max_len':'2048'}"
|
||||
"set group_concat_max_len=4096", "{'group_concat_max_len':'4096'}"
|
||||
"set tx_isolation='READ-COMMITTED', group_concat_max_len=4096", "{'transaction_isolation':'READ-COMMITTED', 'group_concat_max_len':'4096'}"
|
||||
"set tx_isolation='READ-COMMITTED', group_concat_max_len=2048, net_write_timeout=30", "{'transaction_isolation':'READ-COMMITTED', 'group_concat_max_len':'2048', 'net_write_timeout':'30'}"
|
||||
"set group_concat_max_len=4096; ", "{'group_concat_max_len':'4096'}"
|
||||
"SET character_set_database='utf8mb4', max_join_size=10000; ", "{'character_set_database':'utf8mb4', 'max_join_size':'10000'}"
|
||||
"SET character_set_database='utf8mb4', max_join_size=10000, session_track_gtids=OWN_GTID; ", "{'character_set_database':'utf8mb4', 'max_join_size':'10000', 'session_track_gtids':'OWN_GTID'}"
|
||||
"SET sql_select_limit=3030, session_track_gtids=OWN_GTID; SET max_join_size=10000; ", "{'sql_select_limit':'3030', 'max_join_size':'10000', 'session_track_gtids':'OWN_GTID'}"
|
||||
"SET sql_mode='NO_ENGINE_SUBSTITUTION', sql_select_limit=3030, session_track_gtids=OWN_GTID; SET max_join_size=10000; ", "{'sql_mode':'NO_ENGINE_SUBSTITUTION','sql_select_limit':'3030', 'max_join_size':'10000', 'session_track_gtids':'OWN_GTID'}"
|
||||
"SET character_set_client='utf8', sql_select_limit=3030, max_join_size=18446744073709551615", "{'character_set_client':'utf8', 'sql_select_limit':'3030', 'max_join_size':'18446744073709551615'}"
|
||||
"SET sql_select_limit=3030, character_set_client='latin1', max_join_size=10000", "{'sql_select_limit':'3030', 'character_set_client':'latin1', 'max_join_size':'10000'}"
|
||||
"SET session_track_gtids=OFF", "{'session_track_gtids':'OFF'}"
|
||||
"SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION', character_set_client='latin1', max_join_size=10000", "{'time_zone':'+04:00', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'character_set_client':'latin1', 'max_join_size':'10000'}"
|
||||
"SET character_set_results='binary', sql_mode='NO_ENGINE_SUBSTITUTION', character_set_client='latin1', max_join_size=10000", "{'character_set_results':'binary', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'character_set_client':'latin1', 'max_join_size':'10000'}"
|
||||
"SET character_set_results='binary', max_join_size=10000, sql_mode='NO_ENGINE_SUBSTITUTION', character_set_client='latin1'; ", "{'character_set_results':'binary', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'character_set_client':'latin1', 'max_join_size':'10000'}"
|
||||
"SET CHARACTER SET utf8", "{'character_set_results':'utf8', 'character_set_client':'utf8'}", "['character_set_connection', 'collation_connection']"
|
||||
"SET CHARACTER SET 'utf8'", "{'character_set_results':'utf8', 'character_set_client':'utf8'}", "['character_set_connection', 'collation_connection']"
|
||||
"SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION', max_join_size=10000; SET CHARACTER SET 'latin1'", "{'time_zone':'+04:00', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'max_join_size':'10000', 'character_set_results':'latin1', 'character_set_client':'latin1'}", "['character_set_connection', 'collation_connection']"
|
||||
"SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION', max_join_size=10000; SET CHARSET 'latin1'", "{'time_zone':'+04:00', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'max_join_size':'10000', 'character_set_results':'latin1', 'character_set_client':'latin1'}", "['character_set_connection', 'collation_connection']"
|
||||
"SET session_track_gtids=ALL_GTIDS", "{'session_track_gtids':'ALL_GTIDS'}"
|
||||
"SET sql_safe_updates=1, session_track_schema=1, sql_mode = concat(@@sql_mode,',STRICT_TRANS_TABLES')", "{'sql_safe_updates':'ON', 'sql_mode':'concat(@@sql_mode,\',STRICT_TRANS_TABLES\')'}"
|
||||
"set `group_concat_max_len`=4096", "{'group_concat_max_len':'4096'}"
|
||||
"SET `sql_select_limit`=3030; ", "{'sql_select_limit':'3030'}"
|
||||
"SET `time_zone`='+04:00', `sql_mode`='NO_ENGINE_SUBSTITUTION', `max_join_size`=10000; SET CHARACTER SET 'latin1'", "{'time_zone':'+04:00', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'max_join_size':'10000', 'character_set_results':'latin1', 'character_set_client':'latin1'}", "['character_set_connection', 'collation_connection']"
|
||||
"SET `character_set_results`='binary', `sql_mode`='NO_ENGINE_SUBSTITUTION', `character_set_client`='latin1', `max_join_size`=10000", "{'character_set_results':'binary', 'sql_mode':'NO_ENGINE_SUBSTITUTION', 'character_set_client':'latin1', 'max_join_size':'10000'}"
|
||||
"set `tx_isolation`='READ-COMMITTED', `group_concat_max_len`=4096", "{'transaction_isolation':'READ-COMMITTED', 'group_concat_max_len':'4096'}"
|
||||
"set `net_write_timeout`=30", "{'net_write_timeout':'30'}"
|
||||
"SET `sql_auto_is_null`=ON", "{'sql_auto_is_null':'ON'}"
|
||||
"set `character_set_results`=null; set names latin7; set `character_set_client`='utf8mb4';", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'utf8mb4'}"
|
||||
@ -0,0 +1,446 @@
|
||||
std::vector<std::string> split(const std::string& s, char delimiter)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
std::istringstream tokenStream(s);
|
||||
while (std::getline(tokenStream, token, delimiter))
|
||||
{
|
||||
tokens.push_back(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
struct TestCase {
|
||||
std::string command;
|
||||
json expected_vars;
|
||||
json reset_vars;
|
||||
};
|
||||
|
||||
std::vector<TestCase> testCases;
|
||||
|
||||
#define MAX_LINE 10240
|
||||
|
||||
int readTestCases(const std::string& fileName) {
|
||||
FILE* fp = fopen(fileName.c_str(), "r");
|
||||
if (!fp) return 0;
|
||||
|
||||
char buf[MAX_LINE], col1[MAX_LINE], col2[MAX_LINE], col3[MAX_LINE] = {0};
|
||||
int n = 0;
|
||||
for(;;) {
|
||||
if (fgets(buf, sizeof(buf), fp) == NULL) break;
|
||||
n = sscanf(buf, " \"%[^\"]\", \"%[^\"]\", \"%[^\"]\"", col1, col2, col3);
|
||||
if (n == 0) break;
|
||||
|
||||
char *p = col2;
|
||||
while(*p++) if(*p == '\'') *p = '\"';
|
||||
|
||||
json vars = json::parse(col2);
|
||||
|
||||
p = col3;
|
||||
while(col3[0] != 0 && *p++) if(*p == '\'') *p = '\"';
|
||||
|
||||
json reset_vars;
|
||||
if (p != col3) {
|
||||
reset_vars = json::parse(col3);
|
||||
}
|
||||
|
||||
testCases.push_back({col1, vars, reset_vars});
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int readTestCasesJSON(const std::string& fileName) {
|
||||
FILE* fp = fopen(fileName.c_str(), "r");
|
||||
if (!fp) return 0;
|
||||
|
||||
char buf[MAX_LINE] = {0};
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
for(;;) {
|
||||
if (fgets(buf, sizeof(buf), fp) == NULL) break;
|
||||
i++;
|
||||
json j = json::parse(buf);
|
||||
|
||||
// char *p = col2;
|
||||
// while(*p++) if(*p == '\'') *p = '\"';
|
||||
|
||||
//json vars = json::parse(j['expected']);
|
||||
json vars = j["expected"];
|
||||
|
||||
// p = col3;
|
||||
// while(col3[0] != 0 && *p++) if(*p == '\'') *p = '\"';
|
||||
|
||||
json reset_vars;
|
||||
if(j.find("reset") != j.end())
|
||||
reset_vars = j["reset"];
|
||||
// if (p != col3) {
|
||||
// reset_vars = json::parse(col3);
|
||||
// }
|
||||
std::string st = std::string(j["query"].dump(),1,j["query"].dump().length()-2);
|
||||
unsigned int l = st.length();
|
||||
char newbuf[l+1];
|
||||
memset(newbuf,0,l+1);
|
||||
char *s = (char *)st.data();
|
||||
char *d = newbuf;
|
||||
for (unsigned int i=0; i < l; i++) {
|
||||
if ((*s == '\\') && (*(s+1) == '"')) {
|
||||
s++;
|
||||
} else {
|
||||
*d = *s;
|
||||
d++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
testCases.push_back({newbuf, vars, reset_vars});
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long long monotonic_time() {
|
||||
struct timespec ts;
|
||||
//clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); // this is faster, but not precise
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (((unsigned long long) ts.tv_sec) * 1000000) + (ts.tv_nsec / 1000);
|
||||
}
|
||||
|
||||
struct cpu_timer
|
||||
{
|
||||
cpu_timer() {
|
||||
begin = monotonic_time();
|
||||
}
|
||||
~cpu_timer()
|
||||
{
|
||||
unsigned long long end = monotonic_time();
|
||||
std::cerr << double( end - begin ) / 1000000 << " secs.\n" ;
|
||||
begin=end-begin;
|
||||
};
|
||||
unsigned long long begin;
|
||||
};
|
||||
|
||||
|
||||
inline int fastrand() {
|
||||
g_seed = (214014*g_seed+2531011);
|
||||
return (g_seed>>16)&0x7FFF;
|
||||
}
|
||||
|
||||
void parseResultJsonColumn(MYSQL_RES *result, json& j) {
|
||||
if(!result) return;
|
||||
MYSQL_ROW row;
|
||||
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
j = json::parse(row[0]);
|
||||
}
|
||||
|
||||
void parseResult(MYSQL_RES *result, json& j) {
|
||||
if(!result) return;
|
||||
MYSQL_ROW row;
|
||||
|
||||
unsigned long long nr = mysql_num_rows(result);
|
||||
assert(nr > 16);
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
j[row[0]] = row[1];
|
||||
}
|
||||
}
|
||||
|
||||
void dumpResult(MYSQL_RES *result) {
|
||||
if(!result) return;
|
||||
MYSQL_ROW row;
|
||||
|
||||
int num_fields = mysql_num_fields(result);
|
||||
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
for(int i = 0; i < num_fields; i++)
|
||||
{
|
||||
printf("%s ", row[i] ? row[i] : "NULL");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void queryVariables(MYSQL *mysql, json& j, std::string& paddress) {
|
||||
std::stringstream query;
|
||||
if (is_mariadb) {
|
||||
query << "SELECT /* mysql " << mysql << " " << paddress << " */ lower(variable_name), variable_value FROM information_schema.session_variables WHERE variable_name IN "
|
||||
" ("
|
||||
" 'sql_safe_updates', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
|
||||
" 'sql_select_limit', 'character_set_results', 'tx_isolation', 'tx_read_only'";
|
||||
}
|
||||
if (is_cluster) {
|
||||
query << "SELECT /* mysql " << mysql << " " << paddress << " */ * FROM performance_schema.session_variables WHERE variable_name IN "
|
||||
" ("
|
||||
" 'sql_safe_updates', 'session_track_gtids', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
|
||||
" 'sql_select_limit', 'character_set_results', 'transaction_isolation', 'transaction_read_only', "
|
||||
" 'wsrep_sync_wait'";
|
||||
}
|
||||
if (!is_mariadb && !is_cluster) {
|
||||
query << "SELECT /* mysql " << mysql << " " << paddress << " */ * FROM performance_schema.session_variables WHERE variable_name IN "
|
||||
" ("
|
||||
" 'sql_safe_updates', 'session_track_gtids', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
|
||||
" 'sql_select_limit', 'character_set_results', 'transaction_isolation', 'transaction_read_only'";
|
||||
}
|
||||
query << ", 'hostname', 'sql_log_bin', 'sql_mode', 'init_connect', 'time_zone', 'sql_auto_is_null'";
|
||||
query << ", 'sql_auto_is_null', 'collation_connection', 'character_set_connection', 'character_set_client', 'character_set_database', 'group_concat_max_len'";
|
||||
query << ", 'foreign_key_checks', 'unique_checks'";
|
||||
query << ", 'auto_increment_increment', 'auto_increment_offset'";
|
||||
query << ", 'default_storage_engine', 'default_tmp_storage_engine'";
|
||||
query << ", 'innodb_lock_wait_timeout', 'innodb_strict_mode', 'innodb_table_locks'";
|
||||
query << ", 'join_buffer_size', 'lock_wait_timeout'";
|
||||
query << ")";
|
||||
//fprintf(stderr, "TRACE : QUERY 3 : variables %s\n", query.str().c_str());
|
||||
if (mysql_query(mysql, query.str().c_str())) {
|
||||
if (silent==0) {
|
||||
fprintf(stderr,"ERROR while running -- \"%s\" : (%d) %s\n", query.str().c_str(), mysql_errno(mysql), mysql_error(mysql));
|
||||
}
|
||||
} else {
|
||||
MYSQL_RES *result = mysql_store_result(mysql);
|
||||
parseResult(result, j);
|
||||
|
||||
mysql_free_result(result);
|
||||
__sync_fetch_and_add(&g_select_OK,1);
|
||||
}
|
||||
}
|
||||
|
||||
void queryInternalStatus(MYSQL *mysql, json& j, std::string& paddress) {
|
||||
char *query = (char*)"PROXYSQL INTERNAL SESSION";
|
||||
|
||||
//fprintf(stderr, "TRACE : QUERY 4 : variables %s\n", query);
|
||||
if (mysql_query(mysql, query)) {
|
||||
if (silent==0) {
|
||||
fprintf(stderr,"ERROR while running -- \"%s\" : (%d) %s\n", query, mysql_errno(mysql), mysql_error(mysql));
|
||||
}
|
||||
} else {
|
||||
MYSQL_RES *result = mysql_store_result(mysql);
|
||||
parseResultJsonColumn(result, j);
|
||||
|
||||
mysql_free_result(result);
|
||||
__sync_fetch_and_add(&g_select_OK,1);
|
||||
}
|
||||
|
||||
std::vector<std::string> bools_variables = {
|
||||
"sql_auto_is_null",
|
||||
"sql_safe_updates",
|
||||
"foreign_key_checks",
|
||||
"unique_checks"
|
||||
};
|
||||
// value types in mysql and in proxysql are different
|
||||
// we should convert proxysql values to mysql format to compare
|
||||
for (auto& el : j.items()) {
|
||||
if (paddress.length() == 0) {
|
||||
if (el.key() == "address") {
|
||||
paddress = el.value();
|
||||
}
|
||||
}
|
||||
if (el.key() == "conn") {
|
||||
std::string sql_log_bin_value;
|
||||
|
||||
// sql_log_bin {0|1}
|
||||
if (el.value()["sql_log_bin"] == 1) {
|
||||
el.value().erase("sql_log_bin");
|
||||
j["conn"]["sql_log_bin"] = "ON";
|
||||
}
|
||||
else if (el.value()["sql_log_bin"] == 0) {
|
||||
el.value().erase("sql_log_bin");
|
||||
j["conn"]["sql_log_bin"] = "OFF";
|
||||
}
|
||||
|
||||
{
|
||||
for (std::vector<std::string>::iterator it = bools_variables.begin(); it != bools_variables.end(); it++) {
|
||||
std::string v = el.value()[*it].dump();
|
||||
if (
|
||||
(strcasecmp(v.c_str(),"ON")==0)
|
||||
||
|
||||
(strcasecmp(v.c_str(),"1")==0)
|
||||
) {
|
||||
el.value().erase(*it);
|
||||
j["conn"][*it] = "ON";
|
||||
} else {
|
||||
if (
|
||||
(strcasecmp(v.c_str(),"OFF")==0)
|
||||
||
|
||||
(strcasecmp(v.c_str(),"0")==0)
|
||||
) {
|
||||
el.value().erase(*it);
|
||||
j["conn"][*it] = "OFF";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// sql_auto_is_null {true|false}
|
||||
if (!el.value()["sql_auto_is_null"].dump().compare("ON") ||
|
||||
!el.value()["sql_auto_is_null"].dump().compare("1") ||
|
||||
!el.value()["sql_auto_is_null"].dump().compare("on") ||
|
||||
el.value()["sql_auto_is_null"] == 1) {
|
||||
el.value().erase("sql_auto_is_null");
|
||||
j["conn"]["sql_auto_is_null"] = "ON";
|
||||
}
|
||||
else if (!el.value()["sql_auto_is_null"].dump().compare("OFF") ||
|
||||
!el.value()["sql_auto_is_null"].dump().compare("0") ||
|
||||
!el.value()["sql_auto_is_null"].dump().compare("off") ||
|
||||
el.value()["sql_auto_is_null"] == 0) {
|
||||
el.value().erase("sql_auto_is_null");
|
||||
j["conn"]["sql_auto_is_null"] = "OFF";
|
||||
}
|
||||
*/
|
||||
// completely remove autocommit test
|
||||
/*
|
||||
// autocommit {true|false}
|
||||
if (!el.value()["autocommit"].dump().compare("ON") ||
|
||||
!el.value()["autocommit"].dump().compare("1") ||
|
||||
!el.value()["autocommit"].dump().compare("on") ||
|
||||
el.value()["autocommit"] == 1) {
|
||||
el.value().erase("autocommit");
|
||||
j["conn"]["autocommit"] = "ON";
|
||||
}
|
||||
else if (!el.value()["autocommit"].dump().compare("OFF") ||
|
||||
!el.value()["autocommit"].dump().compare("0") ||
|
||||
!el.value()["autocommit"].dump().compare("off") ||
|
||||
el.value()["autocommit"] == 0) {
|
||||
el.value().erase("autocommit");
|
||||
j["conn"]["autocommit"] = "OFF";
|
||||
}
|
||||
*/
|
||||
/*
|
||||
// sql_safe_updates
|
||||
if (!el.value()["sql_safe_updates"].dump().compare("\"ON\"") ||
|
||||
!el.value()["sql_safe_updates"].dump().compare("\"1\"") ||
|
||||
!el.value()["sql_safe_updates"].dump().compare("\"on\"") ||
|
||||
el.value()["sql_safe_updates"] == 1) {
|
||||
el.value().erase("sql_safe_updates");
|
||||
j["conn"]["sql_safe_updates"] = "ON";
|
||||
}
|
||||
else if (!el.value()["sql_safe_updates"].dump().compare("\"OFF\"") ||
|
||||
!el.value()["sql_safe_updates"].dump().compare("\"0\"") ||
|
||||
!el.value()["sql_safe_updates"].dump().compare("\"off\"") ||
|
||||
el.value()["sql_safe_updates"] == 0) {
|
||||
el.value().erase("sql_safe_updates");
|
||||
j["conn"]["sql_safe_updates"] = "OFF";
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << 0xFFFFFFFFFFFFFFFF;
|
||||
// sql_select_limit
|
||||
if (!el.value()["sql_select_limit"].dump().compare("\"DEFAULT\"")) {
|
||||
el.value().erase("sql_select_limit");
|
||||
j["conn"]["sql_select_limit"] = strdup(ss.str().c_str());
|
||||
}
|
||||
|
||||
if (!is_mariadb) {
|
||||
// transaction_isolation (level)
|
||||
if (!el.value()["isolation_level"].dump().compare("\"REPEATABLE READ\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["transaction_isolation"] = "REPEATABLE-READ";
|
||||
}
|
||||
else if (!el.value()["isolation_level"].dump().compare("\"READ COMMITTED\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["transaction_isolation"] = "READ-COMMITTED";
|
||||
}
|
||||
else if (!el.value()["isolation_level"].dump().compare("\"READ UNCOMMITTED\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["transaction_isolation"] = "READ-UNCOMMITTED";
|
||||
}
|
||||
else if (!el.value()["isolation_level"].dump().compare("\"SERIALIZABLE\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["transaction_isolation"] = "SERIALIZABLE";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// transaction_isolation (level)
|
||||
if (!el.value()["isolation_level"].dump().compare("\"REPEATABLE READ\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["tx_isolation"] = "REPEATABLE-READ";
|
||||
}
|
||||
else if (!el.value()["isolation_level"].dump().compare("\"READ COMMITTED\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["tx_isolation"] = "READ-COMMITTED";
|
||||
}
|
||||
else if (!el.value()["isolation_level"].dump().compare("\"READ UNCOMMITTED\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["tx_isolation"] = "READ-UNCOMMITTED";
|
||||
}
|
||||
else if (!el.value()["isolation_level"].dump().compare("\"SERIALIZABLE\"")) {
|
||||
el.value().erase("isolation_level");
|
||||
j["conn"]["tx_isolation"] = "SERIALIZABLE";
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_mariadb) {
|
||||
// transaction_read (write|only)
|
||||
if (!el.value()["transaction_read"].dump().compare("\"ONLY\"")) {
|
||||
el.value().erase("transaction_read");
|
||||
j["conn"]["transaction_read_only"] = "ON";
|
||||
}
|
||||
else if (!el.value()["transaction_read"].dump().compare("\"WRITE\"")) {
|
||||
el.value().erase("transaction_read");
|
||||
j["conn"]["transaction_read_only"] = "OFF";
|
||||
}
|
||||
} else {
|
||||
// transaction_read (write|only)
|
||||
if (!el.value()["transaction_read"].dump().compare("\"ONLY\"")) {
|
||||
el.value().erase("transaction_read");
|
||||
j["conn"]["tx_read_only"] = "ON";
|
||||
}
|
||||
else if (!el.value()["transaction_read"].dump().compare("\"WRITE\"")) {
|
||||
el.value().erase("transaction_read");
|
||||
j["conn"]["tx_read_only"] = "OFF";
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_mariadb) {
|
||||
// session_track_gtids
|
||||
if (!el.value()["session_track_gtids"].dump().compare("\"OFF\"")) {
|
||||
el.value().erase("session_track_gtids");
|
||||
j["conn"]["session_track_gtids"] = "OFF";
|
||||
}
|
||||
else if (!el.value()["session_track_gtids"].dump().compare("\"OWN_GTID\"")) {
|
||||
el.value().erase("session_track_gtids");
|
||||
j["conn"]["session_track_gtids"] = "OWN_GTID";
|
||||
}
|
||||
else if (!el.value()["session_track_gtids"].dump().compare("\"ALL_GTIDS\"")) {
|
||||
el.value().erase("session_track_gtids");
|
||||
j["conn"]["session_track_gtids"] = "ALL_GTIDS";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks that after setting 'session_track_gtids', the new set value follows ProxySQL rules
|
||||
* for this particular variable. This is:
|
||||
* - backend connections are by default set to `mysql-default_session_track_gtids`.
|
||||
* - if `mysql-default_session_track_gtids=OFF` (the default), `session_track_gtids` is not changed on backend.
|
||||
* - if the client asks for `session_track_gtids=OFF`, proxysql ignores it (it just acknowledge it).
|
||||
* - if the client asks for `session_track_gtids=OWN_GTID`, proxysql will apply it.
|
||||
* - if the client asks for `session_track_gtids=ALL_GTIDS`, proxysql will switch to OWN_GTID and generate a warning.
|
||||
* - if the backend doesn't support `session_track_gtids` (for example in MySQL 5.5 and MySQL 5.6), proxysql won't apply it. It knows checking server capabilities
|
||||
*
|
||||
* @param expVal The value to which 'session_track_gtids' have been set.
|
||||
* @param sVal The ProxySQL session value for 'session_track_gtids'.
|
||||
* @param mVal The MySQL session value for 'session_track_gtids'.
|
||||
* @return True in case the check succeed, false otherwise.
|
||||
*/
|
||||
bool check_session_track_gtids(const std::string& expVal, const std::string& sVal, const std::string& mVal) {
|
||||
bool res = false;
|
||||
|
||||
if (expVal == "OFF") {
|
||||
res = expVal == sVal;
|
||||
} else if (expVal == "OWN_GTID" && (sVal == mVal && sVal == "OWN_GTID")) {
|
||||
res = true;
|
||||
} else if (expVal == "ALL_GTIDS" && (sVal == mVal && sVal == "OWN_GTID")) {
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Loading…
Reference in new issue