Adding functions for tracking more variables

Extended unit testing parser
Distinguish between variables that need quote or no quote
pull/2243/head
René Cannaò 7 years ago
parent ddf4a231a3
commit 673bb96cfb

@ -122,6 +122,7 @@ class MySQL_Session
bool handler_again___verify_backend_sql_safe_updates();
bool handler_again___verify_backend_collation_connection();
bool handler_again___verify_backend_net_write_timeout();
bool handler_again___verify_backend_max_join_size();
bool handler_again___verify_backend__generic_variable(uint32_t *be_int, char **be_var, char *def, uint32_t *fe_int, char *fe_var, enum session_status next_sess_status);
bool handler_again___status_SETTING_INIT_CONNECT(int *);
bool handler_again___status_SETTING_LDAP_USER_VARIABLE(int *);
@ -136,7 +137,8 @@ class MySQL_Session
bool handler_again___status_SETTING_SQL_SAFE_UPDATES(int *);
bool handler_again___status_SETTING_COLLATION_CONNECTION(int *);
bool handler_again___status_SETTING_NET_WRITE_TIMEOUT(int *);
bool handler_again___status_SETTING_GENERIC_VARIABLE(int *, char *, char *);
bool handler_again___status_SETTING_MAX_JOIN_SIZE(int *);
bool handler_again___status_SETTING_GENERIC_VARIABLE(int *, char *, char *, bool no_quote=false);
bool handler_again___status_CHANGING_SCHEMA(int *);
bool handler_again___status_CONNECTING_SERVER(int *);
bool handler_again___status_CHANGING_USER_SERVER(int *);

@ -26,7 +26,8 @@
#define MYSQL_DEFAULT_SQL_SELECT_LIMIT ""
#define MYSQL_DEFAULT_SQL_SAFE_UPDATES ""
#define MYSQL_DEFAULT_COLLATION_CONNECTION ""
#define MYSQL_DEFAULT_NET_WRITE_TIMEOUT ""
#define MYSQL_DEFAULT_NET_WRITE_TIMEOUT "60"
#define MYSQL_DEFAULT_MAX_JOIN_SIZE "18446744073709551615"
static unsigned int near_pow_2 (unsigned int n) {
unsigned int i = 1;
@ -457,6 +458,7 @@ class MySQL_Threads_Handler
char *default_sql_safe_updates;
char *default_collation_connection;
char *default_net_write_timeout;
char *default_max_join_size;
#ifdef DEBUG
bool session_debug;
#endif /* DEBUG */

@ -52,6 +52,7 @@ class MySQL_Connection {
uint32_t sql_safe_updates_int;
uint32_t collation_connection_int;
uint32_t net_write_timeout_int;
uint32_t max_join_size_int;
uint32_t max_allowed_pkt;
uint32_t server_capabilities;
uint32_t client_flag;
@ -66,6 +67,7 @@ class MySQL_Connection {
char * sql_safe_updates;
char * collation_connection;
char * net_write_timeout;
char * max_join_size;
bool isolation_level_sent;
bool character_set_results_sent;
bool session_track_gtids_sent;
@ -74,6 +76,7 @@ class MySQL_Connection {
bool sql_safe_updates_sent;
bool collation_connection_sent;
bool net_write_timeout_sent;
bool max_join_size_sent;
bool sql_mode_sent;
char *ldap_user_variable;
char *ldap_user_variable_value;

@ -160,6 +160,7 @@ enum session_status {
SETTING_SQL_SAFE_UPDATES,
SETTING_COLLATION_CONNECTION,
SETTING_NET_WRITE_TIMEOUT,
SETTING_MAX_JOIN_SIZE,
FAST_FORWARD,
PROCESSING_STMT_PREPARE,
PROCESSING_STMT_EXECUTE,
@ -628,6 +629,7 @@ __thread char *mysql_thread___default_sql_select_limit;
__thread char *mysql_thread___default_sql_safe_updates;
__thread char *mysql_thread___default_collation_connection;
__thread char *mysql_thread___default_net_write_timeout;
__thread char *mysql_thread___default_max_join_size;
__thread int mysql_thread___max_allowed_packet;
__thread int mysql_thread___throttle_connections_per_sec_to_hostgroup;
__thread int mysql_thread___max_transaction_time;
@ -770,6 +772,7 @@ extern __thread char *mysql_thread___default_sql_select_limit;
extern __thread char *mysql_thread___default_sql_safe_updates;
extern __thread char *mysql_thread___default_collation_connection;
extern __thread char *mysql_thread___default_net_write_timeout;
extern __thread char *mysql_thread___default_max_join_size;
extern __thread int mysql_thread___max_allowed_packet;
extern __thread int mysql_thread___throttle_connections_per_sec_to_hostgroup;
extern __thread int mysql_thread___max_transaction_time;

@ -1761,6 +1761,19 @@ bool MySQL_Session::handler_again___verify_backend_net_write_timeout() {
return ret;
}
bool MySQL_Session::handler_again___verify_backend_max_join_size() {
bool ret = false;
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.max_join_size_int,
&mybe->server_myds->myconn->options.max_join_size,
mysql_thread___default_max_join_size,
&client_myds->myconn->options.max_join_size_int,
client_myds->myconn->options.max_join_size,
SETTING_MAX_JOIN_SIZE
);
return ret;
}
bool MySQL_Session::handler_again___verify_init_connect() {
if (mybe->server_myds->myconn->options.init_connect_sent==false) {
// we needs to set it to true
@ -2288,7 +2301,7 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_MODE(int *_rc) {
}
*/
bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, char *var_name, char *var_value) {
bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, char *var_name, char *var_value, bool no_quote) {
bool ret = false;
assert(mybe->server_myds->myconn);
MySQL_Data_Stream *myds=mybe->server_myds;
@ -2302,15 +2315,19 @@ bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, ch
unsigned long query_length=0;
if (myconn->async_state_machine==ASYNC_IDLE) {
char *q = NULL;
q=(char *)"SET %s='%s'"; // default
if (var_value[0]=='@') {
q=(char *)"SET %s=%s";}
if (strncasecmp(var_value,(char *)"CONCAT",6)==0)
q=(char *)"SET %s=%s";
if (strncasecmp(var_value,(char *)"IFNULL",6)==0)
q=(char *)"SET %s=%s";
if (strncasecmp(var_value,(char *)"REPLACE",7)==0)
if (no_quote) {
q=(char *)"SET %s=%s";
} else {
q=(char *)"SET %s='%s'"; // default
if (var_value[0]=='@') {
q=(char *)"SET %s=%s";}
if (strncasecmp(var_value,(char *)"CONCAT",6)==0)
q=(char *)"SET %s=%s";
if (strncasecmp(var_value,(char *)"IFNULL",6)==0)
q=(char *)"SET %s=%s";
if (strncasecmp(var_value,(char *)"REPLACE",7)==0)
q=(char *)"SET %s=%s";
}
query=(char *)malloc(strlen(q)+strlen(var_value));
sprintf(query,q,var_name, var_value);
query_length=strlen(query);
@ -2381,35 +2398,35 @@ bool MySQL_Session::handler_again___status_SETTING_ISOLATION_LEVEL(int *_rc) {
bool MySQL_Session::handler_again___status_SETTING_CHARACTER_SET_RESULTS(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"CHARACTER_SET_RESULTS", mybe->server_myds->myconn->options.character_set_results);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"CHARACTER_SET_RESULTS", mybe->server_myds->myconn->options.character_set_results, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SESSION_TRACK_GTIDS", mybe->server_myds->myconn->options.session_track_gtids);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SESSION_TRACK_GTIDS", mybe->server_myds->myconn->options.session_track_gtids, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_AUTO_IS_NULL(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_AUTO_IS_NULL", mybe->server_myds->myconn->options.sql_auto_is_null);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_AUTO_IS_NULL", mybe->server_myds->myconn->options.sql_auto_is_null, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_SELECT_LIMIT(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SELECT_LIMIT", mybe->server_myds->myconn->options.sql_select_limit);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SELECT_LIMIT", mybe->server_myds->myconn->options.sql_select_limit, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_SAFE_UPDATES(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SAFE_UPDATES", mybe->server_myds->myconn->options.sql_safe_updates);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SAFE_UPDATES", mybe->server_myds->myconn->options.sql_safe_updates, true);
return ret;
}
@ -2423,7 +2440,14 @@ bool MySQL_Session::handler_again___status_SETTING_COLLATION_CONNECTION(int *_rc
bool MySQL_Session::handler_again___status_SETTING_NET_WRITE_TIMEOUT(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"NET_WRITE_TIMEOUT", mybe->server_myds->myconn->options.net_write_timeout);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"NET_WRITE_TIMEOUT", mybe->server_myds->myconn->options.net_write_timeout, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_MAX_JOIN_SIZE(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"MAX_JOIN_SIZE", mybe->server_myds->myconn->options.max_join_size, true);
return ret;
}
@ -3678,6 +3702,9 @@ handler_again:
if (handler_again___verify_backend_net_write_timeout()) {
goto handler_again;
}
if (handler_again___verify_backend_max_join_size()) {
goto handler_again;
}
}
if (status==PROCESSING_STMT_EXECUTE) {
CurrentQuery.mysql_stmt=myconn->local_stmts->find_backend_stmt_by_global_id(CurrentQuery.stmt_global_id);
@ -4247,6 +4274,78 @@ handler_again:
}
break;
case SETTING_SQL_AUTO_IS_NULL:
{
int rc=0;
if (handler_again___status_SETTING_SQL_AUTO_IS_NULL(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_SQL_SELECT_LIMIT:
{
int rc=0;
if (handler_again___status_SETTING_SQL_SELECT_LIMIT(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_SQL_SAFE_UPDATES:
{
int rc=0;
if (handler_again___status_SETTING_SQL_SAFE_UPDATES(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_COLLATION_CONNECTION:
{
int rc=0;
if (handler_again___status_SETTING_COLLATION_CONNECTION(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_NET_WRITE_TIMEOUT:
{
int rc=0;
if (handler_again___status_SETTING_NET_WRITE_TIMEOUT(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_MAX_JOIN_SIZE:
{
int rc=0;
if (handler_again___status_SETTING_MAX_JOIN_SIZE(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_INIT_CONNECT:
{
int rc=0;

@ -339,6 +339,7 @@ static char * mysql_thread_variables_names[]= {
(char *)"default_sql_safe_updates",
(char *)"default_collation_connection",
(char *)"default_net_write_timeout",
(char *)"default_max_join_size",
(char *)"connpoll_reset_queue_length",
(char *)"min_num_servers_lantency_awareness",
(char *)"stats_time_backend_query",
@ -444,6 +445,7 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() {
variables.default_sql_safe_updates=strdup((char *)MYSQL_DEFAULT_SQL_SAFE_UPDATES);
variables.default_collation_connection=strdup((char *)MYSQL_DEFAULT_COLLATION_CONNECTION);
variables.default_net_write_timeout=strdup((char *)MYSQL_DEFAULT_NET_WRITE_TIMEOUT);
variables.default_max_join_size=strdup((char *)MYSQL_DEFAULT_MAX_JOIN_SIZE);
variables.ping_interval_server_msec=10000;
variables.ping_timeout_server=200;
variables.default_schema=strdup((char *)"information_schema");
@ -694,6 +696,12 @@ char * MySQL_Threads_Handler::get_variable_string(char *name) {
}
return strdup(variables.default_net_write_timeout);
}
if (!strcmp(name,"default_max_join_size")) {
if (variables.default_max_join_size==NULL) {
variables.default_max_join_size=strdup((char *)MYSQL_DEFAULT_MAX_JOIN_SIZE);
}
return strdup(variables.default_max_join_size);
}
if (!strcmp(name,"server_version")) return strdup(variables.server_version);
if (!strcmp(name,"eventslog_filename")) return strdup(variables.eventslog_filename);
if (!strcmp(name,"auditlog_filename")) return strdup(variables.auditlog_filename);
@ -979,6 +987,12 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f
}
return strdup(variables.default_net_write_timeout);
}
if (!strcasecmp(name,"default_max_join_size")) {
if (variables.default_max_join_size==NULL) {
variables.default_max_join_size=strdup((char *)MYSQL_DEFAULT_MAX_JOIN_SIZE);
}
return strdup(variables.default_max_join_size);
}
if (!strcasecmp(name,"server_version")) return strdup(variables.server_version);
if (!strcasecmp(name,"auditlog_filename")) return strdup(variables.auditlog_filename);
if (!strcasecmp(name,"eventslog_filename")) return strdup(variables.eventslog_filename);
@ -2320,6 +2334,19 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t
return true;
}
if (!strcasecmp(name,"default_max_join_size")) {
if (variables.default_max_join_size) free(variables.default_max_join_size);
variables.default_max_join_size=NULL;
if (vallen) {
if (strcmp(value,"(null)"))
variables.default_max_join_size=strdup(value);
}
if (variables.default_max_join_size==NULL) {
variables.default_max_join_size=strdup((char *)MYSQL_DEFAULT_MAX_JOIN_SIZE); // default
}
return true;
}
if (!strcasecmp(name,"keep_multiplexing_variables")) {
if (vallen) {
free(variables.keep_multiplexing_variables);
@ -2938,6 +2965,7 @@ MySQL_Threads_Handler::~MySQL_Threads_Handler() {
if (variables.default_sql_safe_updates) free(variables.default_sql_safe_updates);
if (variables.default_collation_connection) free(variables.default_collation_connection);
if (variables.default_net_write_timeout) free(variables.default_net_write_timeout);
if (variables.default_max_join_size) free(variables.default_max_join_size);
if (variables.eventslog_filename) free(variables.eventslog_filename);
if (variables.auditlog_filename) free(variables.auditlog_filename);
if (variables.ssl_p2s_ca) free(variables.ssl_p2s_ca);
@ -3066,6 +3094,7 @@ MySQL_Thread::~MySQL_Thread() {
if (mysql_thread___default_sql_safe_updates) { free(mysql_thread___default_sql_safe_updates); mysql_thread___default_sql_safe_updates=NULL; }
if (mysql_thread___default_collation_connection) { free(mysql_thread___default_collation_connection); mysql_thread___default_collation_connection=NULL; }
if (mysql_thread___default_net_write_timeout) { free(mysql_thread___default_net_write_timeout); mysql_thread___default_net_write_timeout=NULL; }
if (mysql_thread___default_max_join_size) { free(mysql_thread___default_max_join_size); mysql_thread___default_max_join_size=NULL; }
if (mysql_thread___eventslog_filename) { free(mysql_thread___eventslog_filename); mysql_thread___eventslog_filename=NULL; }
if (mysql_thread___auditlog_filename) { free(mysql_thread___auditlog_filename); mysql_thread___auditlog_filename=NULL; }
if (mysql_thread___ssl_p2s_ca) { free(mysql_thread___ssl_p2s_ca); mysql_thread___ssl_p2s_ca=NULL; }
@ -3176,6 +3205,13 @@ MySQL_Session * MySQL_Thread::create_new_session_and_client_data_stream(int _fd)
}
sess->client_myds->myconn->options.net_write_timeout=strdup(mysql_thread___default_net_write_timeout);
uint32_t max_join_size_int=SpookyHash::Hash32(mysql_thread___default_max_join_size,strlen(mysql_thread___default_max_join_size),10);
sess->client_myds->myconn->options.max_join_size_int = max_join_size_int;
if (sess->client_myds->myconn->options.max_join_size) {
free(sess->client_myds->myconn->options.max_join_size);
}
sess->client_myds->myconn->options.max_join_size=strdup(mysql_thread___default_max_join_size);
return sess;
}
@ -4251,6 +4287,8 @@ void MySQL_Thread::refresh_variables() {
mysql_thread___default_collation_connection=GloMTH->get_variable_string((char *)"default_collation_connection");
if (mysql_thread___default_net_write_timeout) free(mysql_thread___default_net_write_timeout);
mysql_thread___default_net_write_timeout=GloMTH->get_variable_string((char *)"default_net_write_timeout");
if (mysql_thread___default_max_join_size) free(mysql_thread___default_max_join_size);
mysql_thread___default_max_join_size=GloMTH->get_variable_string((char *)"default_max_join_size");
if (mysql_thread___server_version) free(mysql_thread___server_version);
mysql_thread___server_version=GloMTH->get_variable_string((char *)"server_version");
if (mysql_thread___eventslog_filename) free(mysql_thread___eventslog_filename);

@ -214,6 +214,7 @@ MySQL_Connection::MySQL_Connection() {
options.sql_safe_updates = NULL;
options.collation_connection = NULL;
options.net_write_timeout = NULL;
options.max_join_size = NULL;
options.isolation_level_sent = false;
options.character_set_results_sent = false;
options.session_track_gtids_sent = false;
@ -222,6 +223,7 @@ MySQL_Connection::MySQL_Connection() {
options.sql_safe_updates_sent = false;
options.collation_connection_sent = false;
options.net_write_timeout_sent = false;
options.max_join_size_sent = false;
options.sql_mode_sent=false;
options.ldap_user_variable=NULL;
options.ldap_user_variable_value=NULL;
@ -268,6 +270,7 @@ MySQL_Connection::~MySQL_Connection() {
if (options.sql_safe_updates) free(options.sql_safe_updates);
if (options.collation_connection) free(options.collation_connection);
if (options.net_write_timeout) free(options.net_write_timeout);
if (options.max_join_size) free(options.max_join_size);
if (options.ldap_user_variable) free(options.ldap_user_variable);
if (options.ldap_user_variable_value) free(options.ldap_user_variable_value);
if (userinfo) {
@ -2069,6 +2072,12 @@ void MySQL_Connection::reset() {
options.net_write_timeout = NULL;
options.net_write_timeout_sent = false;
}
options.max_join_size_int = 0;
if (options.max_join_size) {
free (options.max_join_size);
options.max_join_size = NULL;
options.max_join_size_sent = false;
}
if (options.init_connect) {
free(options.init_connect);
options.init_connect = NULL;

@ -124,6 +124,7 @@ static Test time_zone[] = {
{ "SET @@time_zone = \"Europe/Paris\"", { Expected("time_zone", {"Europe/Paris"}) } },
{ "SET @@time_zone = \"+00:00\"", { Expected("time_zone", {"+00:00"}) } },
{ "SET @@time_zone = @OLD_TIME_ZONE", { Expected("time_zone", {"@OLD_TIME_ZONE"}) } },
{ "SET @@TIME_ZONE = @OLD_TIME_ZONE", { Expected("time_zone", {"@OLD_TIME_ZONE"}) } },
};
TEST(TestParse, SET_TIME_ZONE) {
@ -166,6 +167,29 @@ static Test names[] = {
TEST(TestParse, SET_NAMES) {
TestParse(names, arraysize(names), "names");
}
static Test various[] = {
{ "SET @@SESSION.SQL_SELECT_LIMIT= DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } },
{ "SET @@SQL_SELECT_LIMIT= DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } },
{ "SET SESSION SQL_SELECT_LIMIT = DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } },
{ "SET @@SESSION.SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } },
{ "SET @@SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } },
{ "SET SESSION SQL_SELECT_LIMIT = 1234", { Expected("sql_select_limit", {"1234"}) } },
{ "SET @@SESSION.SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } },
{ "SET @@SESSION.SQL_SELECT_LIMIT= @old_sql_select_limit", { Expected("sql_select_limit", {"@old_sql_select_limit"}) } },
{ "SET SQL_SELECT_LIMIT= @old_sql_select_limit", { Expected("sql_select_limit", {"@old_sql_select_limit"}) } },
{ "SET @@SESSION.sql_auto_is_null = 0", { Expected("sql_auto_is_null", {"0"}) } },
{ "SET SESSION sql_auto_is_null = 1", { Expected("sql_auto_is_null", {"1"}) } },
{ "SET sql_auto_is_null = OFF", { Expected("sql_auto_is_null", {"OFF"}) } },
{ "SET @@sql_auto_is_null = ON", { Expected("sql_auto_is_null", {"ON"}) } },
{ "SET @@SESSION.sql_safe_updates = 0", { Expected("sql_safe_updates", {"0"}) } },
{ "SET SESSION sql_safe_updates = 1", { Expected("sql_safe_updates", {"1"}) } },
{ "SET SQL_SAFE_UPDATES = OFF", { Expected("sql_safe_updates", {"OFF"}) } },
{ "SET @@sql_safe_updates = ON", { Expected("sql_safe_updates", {"ON"}) } },
};
TEST(TestParse, SET_VARIOUS) {
TestParse(various, arraysize(various), "various");
}
static Test multiple[] = {
{ "SET time_zone = 'Europe/Paris', sql_mode = 'TRADITIONAL'", { Expected("time_zone", {"Europe/Paris"}), Expected("sql_mode", {"TRADITIONAL"}) } },

Loading…
Cancel
Save