From 230345c98ce88bceabec405f9facf088845bf514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 17 Oct 2018 10:49:38 +0300 Subject: [PATCH 1/6] Fix on_queries documentation The combination of values was not documented. --- Documentation/Filters/Database-Firewall-Filter.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/Filters/Database-Firewall-Filter.md b/Documentation/Filters/Database-Firewall-Filter.md index 704b585c4..bb801bdc6 100644 --- a/Documentation/Filters/Database-Firewall-Filter.md +++ b/Documentation/Filters/Database-Firewall-Filter.md @@ -324,6 +324,9 @@ values are: |use |USE operations | |load |LOAD DATA operations | +Multiple values can be combined using the pipe character `|` e.g. +` on_queries select|insert|update`. + ### Applying rules to users The `users` directive defines the users to which the rule should be applied. From 457d0c21dde489e1dab0f954aa5cb72c061f97f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 17 Oct 2018 11:01:39 +0300 Subject: [PATCH 2/6] Document error code and SQL state for blocked queries If the dbfwfilter blocks a query a specific error is returned. This was not documented and is needed to detect errors sent by the filter. --- Documentation/Filters/Database-Firewall-Filter.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/Filters/Database-Firewall-Filter.md b/Documentation/Filters/Database-Firewall-Filter.md index bb801bdc6..7c3401919 100644 --- a/Documentation/Filters/Database-Firewall-Filter.md +++ b/Documentation/Filters/Database-Firewall-Filter.md @@ -88,6 +88,9 @@ action=block rules=/home/user/blacklist-rules.txt ``` +If a query is blocked, the filter will return an error to the client with the +error number 1141 and an SQL state of HY000. + #### `log_match` Log all queries that match a rule. For the `any` matching mode, the name of the From f8cf5053bd6891639aaa51b8a47dc9c838ffbb86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Oct 2018 20:26:58 +0300 Subject: [PATCH 3/6] MXS-2103: Fix CREATE TEMPORARY TABLE detection The table creation was not detected as the function used to extract the table name did not return the fully qualified names. Even if it did return a fully qualified name, it wouldn't have been correctly processed. --- maxscale-system-test/temporal_tables.cpp | 7 +++++ .../readwritesplit/rwsplit_tmp_table_multi.cc | 28 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/maxscale-system-test/temporal_tables.cpp b/maxscale-system-test/temporal_tables.cpp index beaded2e9..ec34c5696 100644 --- a/maxscale-system-test/temporal_tables.cpp +++ b/maxscale-system-test/temporal_tables.cpp @@ -58,5 +58,12 @@ int main(int argc, char *argv[]) test.maxscales->close_maxscale_connections(0); + // MXS-2103 + test.maxscales->connect(); + test.try_query(test.maxscales->conn_rwsplit[0], "CREATE TEMPORARY TABLE temp.dummy5 (dum INT);"); + test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO temp.dummy5 VALUES(1),(2);"); + test.try_query(test.maxscales->conn_rwsplit[0], "SELECT * FROM temp.dummy5;"); + test.maxscales->disconnect(); + return test.global_result; } diff --git a/server/modules/routing/readwritesplit/rwsplit_tmp_table_multi.cc b/server/modules/routing/readwritesplit/rwsplit_tmp_table_multi.cc index a9e134eeb..afd51eb8c 100644 --- a/server/modules/routing/readwritesplit/rwsplit_tmp_table_multi.cc +++ b/server/modules/routing/readwritesplit/rwsplit_tmp_table_multi.cc @@ -169,20 +169,36 @@ void check_create_tmp_table(RWSplitSession *router_cli_ses, router_cli_ses->client_dcb->data); router_cli_ses->have_tmp_tables = true; - char* tblname = qc_get_created_table_name(querybuf); + int size = 0; + char** tblname = qc_get_table_names(querybuf, &size, true); std::string table; - if (tblname && *tblname && strchr(tblname, '.') == NULL) + for (int i = 0; i < size; i++) { - const char* db = mxs_mysql_get_current_db(router_cli_ses->client_dcb->session); - table += db; - table += "."; - table += tblname; + if (tblname[i] && *tblname[i]) + { + table = tblname[i]; + + if (strchr(tblname[i], '.') == NULL) + { + const char* db = mxs_mysql_get_current_db(router_cli_ses->client_dcb->session); + table = db; + table += "."; + table += tblname[i]; + } + break; + } } + MXS_INFO("Added temporary table %s", table.c_str()); + /** Add the table to the set of temporary tables */ router_cli_ses->temp_tables.insert(table); + for (int i = 0; i < size; i++) + { + MXS_FREE(tblname[i]); + } MXS_FREE(tblname); } } From 6d00dbfc92dba65f4e4bb46c049f84b7fbaf4042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sat, 29 Sep 2018 20:10:27 +0300 Subject: [PATCH 4/6] Fix mxs2043_select_for_update Explicitly define the host of the user being created and sync replication after it. --- maxscale-system-test/mxs2043_select_for_update.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/maxscale-system-test/mxs2043_select_for_update.cpp b/maxscale-system-test/mxs2043_select_for_update.cpp index 952c91dc3..2b6c9e518 100644 --- a/maxscale-system-test/mxs2043_select_for_update.cpp +++ b/maxscale-system-test/mxs2043_select_for_update.cpp @@ -78,7 +78,7 @@ bool create_user(TestConnections& test, MYSQL* pMysql) drop_user(test, pMysql, true); - test.try_query(pMysql, "CREATE USER '%s' IDENTIFIED by '%s'", ZUSER, ZPASSWORD); + test.try_query(pMysql, "CREATE USER '%s'@'%%' IDENTIFIED by '%s'", ZUSER, ZPASSWORD); test.try_query(pMysql, "GRANT SELECT, UPDATE ON %s TO '%s'@'%%'", ZTABLE, ZUSER); return test.global_result == 0; @@ -150,6 +150,8 @@ int main(int argc, char* argv[]) if (create_user(test, pMysql)) { int rv = test.repl->connect(); + test.repl->sync_slaves(); + test.expect(rv == 0, "Could not connect to MS."); if (rv == 0) From 192563a947d6bbfcc668cc61fca9f7631a2939de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 17 Oct 2018 15:32:52 +0300 Subject: [PATCH 5/6] MXS-2108: Fix open connection calculation When a connection to a server is lost and the session command history is disabled, the session will continue as long as at least one connection is open. Previously the open connection calculation used the same code that was used when a new session was created which only inspected the configured server count instead of the actual open connection count. --- .../modules/routing/readwritesplit/readwritesplit.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/server/modules/routing/readwritesplit/readwritesplit.cc b/server/modules/routing/readwritesplit/readwritesplit.cc index 1e38b2618..c3aeddbc3 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.cc +++ b/server/modules/routing/readwritesplit/readwritesplit.cc @@ -433,14 +433,21 @@ static bool handle_error_new_connection(RWSplit *inst, } int max_nslaves = inst->max_slave_count(); - bool succp; + bool succp = false; /** * Try to get replacement slave or at least the minimum * number of slave connections for router session. */ if (inst->config().disable_sescmd_history) { - succp = inst->have_enough_servers(); + for (auto it = myrses->backends.begin(); it != myrses->backends.end(); it++) + { + if ((*it)->in_use()) + { + succp = true; + break; + } + } } else { From 262f1d7e471bacca6b985ec3f2cd5cb76d6e2584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Oct 2018 02:06:58 +0300 Subject: [PATCH 6/6] Fix build failures The freopen return value caused warnings. --- server/core/log_manager.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/server/core/log_manager.cc b/server/core/log_manager.cc index d625235a4..3d2194b87 100644 --- a/server/core/log_manager.cc +++ b/server/core/log_manager.cc @@ -576,8 +576,11 @@ static bool logmanager_init_nomutex(const char* ident, if (redirect_stdout) { // Redirect stdout and stderr to the log file - freopen(lm->lm_logfile.lf_full_file_name, "a", stdout); - freopen(lm->lm_logfile.lf_full_file_name, "a", stderr); + if (!freopen(lm->lm_logfile.lf_full_file_name, "a", stdout) || + !freopen(lm->lm_logfile.lf_full_file_name, "a", stderr)) + { + fprintf(stderr, "Error: Failed to redirect stdout/stderr to log file.\n"); + } } return_succ: @@ -2166,8 +2169,12 @@ static bool thr_flush_file(logmanager_t *lm, filewriter_t *fwr) else if (redirect_stdout) { // Redirect stdout and stderr to the new log file - freopen(lf->lf_full_file_name, "a", stdout); - freopen(lf->lf_full_file_name, "a", stderr); + if (!freopen(lf->lf_full_file_name, "a", stdout) || + !freopen(lf->lf_full_file_name, "a", stderr)) + { + LOG_ERROR("MaxScale Log: Error, could not redirect stdout/stderr to log file %s.\n", + lf->lf_full_file_name); + } } }