diff --git a/Documentation/Release-Notes/MaxScale-2.2.14-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.2.14-Release-Notes.md new file mode 100644 index 000000000..55a0de2a5 --- /dev/null +++ b/Documentation/Release-Notes/MaxScale-2.2.14-Release-Notes.md @@ -0,0 +1,51 @@ +# MariaDB MaxScale 2.2.14 Release Notes + +Release 2.2.14 is a GA release. + +This document describes the changes in release 2.2.14, when compared to +release 2.2.13. + +For any problems you encounter, please consider submitting a bug +report on [our Jira](https://jira.mariadb.org/projects/MXS). + +## New Features + +### Avrorouter Table Filtering + +The tables that the avrorouter processes can now be filtered with two new +parameters: [`match`](../Routers/Avrorouter.md#match) and +[`exclude`](../Routers/Avrorouter.md#exclude). + +## Bug fixes + +* [MXS-2034](https://jira.mariadb.org/browse/MXS-2034) query_retry_timeout was not set +* [MXS-2027](https://jira.mariadb.org/browse/MXS-2027) LOAD DATA LOCAL INFILE is not ignored by protocol modules +* [MXS-2024](https://jira.mariadb.org/browse/MXS-2024) Crash in reauthenticate_client +* [MXS-2019](https://jira.mariadb.org/browse/MXS-2019) All atexit handlers aren't called +* [MXS-2015](https://jira.mariadb.org/browse/MXS-2015) CDC Connector ignores errors after registration is successful +* [MXS-2007](https://jira.mariadb.org/browse/MXS-2007) Fatal: MaxScale 2.2.13 received fatal signal 11 (Aurora Monitor) +* [MXS-1999](https://jira.mariadb.org/browse/MXS-1999) Invalid null relationship handling in REST API +* [MXS-1996](https://jira.mariadb.org/browse/MXS-1996) Avrorouter writes misleading error messages to the log +* [MXS-1880](https://jira.mariadb.org/browse/MXS-1880) MaxScale 2.2.5-1 Crashes after a non clean Start +* [MXS-1736](https://jira.mariadb.org/browse/MXS-1736) Clarify the usage of maxpasswd in documentation +* [MXS-1735](https://jira.mariadb.org/browse/MXS-1735) Clarify SSL documentation + +## Known Issues and Limitations + +There are some limitations and known issues within this version of MaxScale. +For more information, please refer to the [Limitations](../About/Limitations.md) document. + +## Packaging + +RPM and Debian packages are provided for supported the Linux distributions. + +Packages can be downloaded [here](https://mariadb.com/downloads/mariadb-tx/maxscale). + +## Source Code + +The source code of MaxScale is tagged at GitHub with a tag, which is identical +with the version of MaxScale. For instance, the tag of version X.Y.Z of MaxScale +is `maxscale-X.Y.Z`. Further, the default branch is always the latest GA version +of MaxScale. + +The source code is available [here](https://github.com/mariadb-corporation/MaxScale). diff --git a/Documentation/Routers/Avrorouter.md b/Documentation/Routers/Avrorouter.md index 311cf255e..5b8d2448c 100644 --- a/Documentation/Routers/Avrorouter.md +++ b/Documentation/Routers/Avrorouter.md @@ -66,6 +66,21 @@ _deflate_. These are the mandatory compression algorithms required by the Avro specification. For more information about the compression types, refer to the [Avro specification](https://avro.apache.org/docs/current/spec.html#Required+Codecs). +### `match` + +Only process events for tables that match this PCRE2 regular expression. See +[Regular Expressions](../Getting-Started/Configuration-Guide.md#regular-expressions) +for more information about regular expressions. + +This parameter was added in MaxScale 2.2.14. + +### `exclude` + +Ignore events for tables that match this PCRE2 regular expression. This can be +combined with the `match` parameter to implement table event filtering. + +This parameter was added in MaxScale 2.2.14. + **Note:** Since the 2.1 version of MaxScale, all of the router options can also be defined as parameters. diff --git a/maxscale-system-test/mdbci/run_test_snapshot.sh b/maxscale-system-test/mdbci/run_test_snapshot.sh index 33432f2a1..b84a3e698 100755 --- a/maxscale-system-test/mdbci/run_test_snapshot.sh +++ b/maxscale-system-test/mdbci/run_test_snapshot.sh @@ -58,13 +58,23 @@ fi . ${script_dir}/set_env.sh "$name" -${mdbci_dir}/mdbci sudo --command 'yum remove maxscale -y' $name/maxscale -${mdbci_dir}/mdbci sudo --command 'yum clean all' $name/maxscale +if [ ${maxscale_N} -gt 1 ] ; then + maxscales_vm=`env | grep maxscale | grep network | sed 's/_network.*//' | grep "_"` +else + maxscales_vm="maxscale" +fi -${mdbci_dir}/mdbci setup_repo --product maxscale_ci --product-version ${target} $name/maxscale -${mdbci_dir}/mdbci install_product --product maxscale_ci $name/maxscale +for maxscale_vm_name in ${maxscales_vm} +do + ${mdbci_dir}/mdbci sudo --command 'yum remove maxscale -y' $name/${maxscale_vm_name} + ${mdbci_dir}/mdbci sudo --command 'yum clean all' $name/${maxscale_vm_name} + + ${mdbci_dir}/mdbci setup_repo --product maxscale_ci --product-version ${target} $name/${maxscale_vm_name} + ${mdbci_dir}/mdbci install_product --product maxscale_ci $name/${maxscale_vm_name} + + checkExitStatus $? "Error installing Maxscale" $snapshot_lock_file +done -checkExitStatus $? "Error installing Maxscale" $snapshot_lock_file cd ${script_dir}/../../ diff --git a/server/modules/routing/avrorouter/avro.cc b/server/modules/routing/avrorouter/avro.cc index 5f1cd6ae4..7fa6def4b 100644 --- a/server/modules/routing/avrorouter/avro.cc +++ b/server/modules/routing/avrorouter/avro.cc @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -138,7 +139,8 @@ Avro::Avro(SERVICE* service, MXS_CONFIG_PARAMETER* params, SERVICE* source, SRow row_count(0), row_target(config_get_integer(params, "group_rows")), task_handle(0), - handler(service, handler) + handler(service, handler, config_get_compiled_regex(params, "match", 0, NULL), + config_get_compiled_regex(params, "exclude", 0, NULL)) { if (source) { diff --git a/server/modules/routing/avrorouter/avro_main.cc b/server/modules/routing/avrorouter/avro_main.cc index 658193ad6..ca9bee06e 100644 --- a/server/modules/routing/avrorouter/avro_main.cc +++ b/server/modules/routing/avrorouter/avro_main.cc @@ -513,6 +513,8 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE() {"start_index", MXS_MODULE_PARAM_COUNT, "1"}, {"block_size", MXS_MODULE_PARAM_SIZE, "0"}, {"codec", MXS_MODULE_PARAM_ENUM, "null", MXS_MODULE_OPT_ENUM_UNIQUE, codec_values}, + {"match", MXS_MODULE_PARAM_REGEX}, + {"exclude", MXS_MODULE_PARAM_REGEX}, {MXS_END_MODULE_PARAMS} } }; diff --git a/server/modules/routing/avrorouter/avro_rbr.cc b/server/modules/routing/avrorouter/avro_rbr.cc index 8f5effa77..2f0adfda4 100644 --- a/server/modules/routing/avrorouter/avro_rbr.cc +++ b/server/modules/routing/avrorouter/avro_rbr.cc @@ -472,6 +472,12 @@ bool Rpl::handle_table_map_event(REP_HEADER *hdr, uint8_t *ptr) int ev_len = m_event_type_hdr_lens[hdr->event_type]; read_table_info(ptr, ev_len, &id, table_ident, sizeof(table_ident)); + + if (!table_matches(table_ident)) + { + return true; + } + auto create = m_created_tables.find(table_ident); if (create != m_created_tables.end()) @@ -600,6 +606,11 @@ bool Rpl::handle_row_event(REP_HEADER *hdr, uint8_t *ptr) char table_ident[MYSQL_TABLE_MAXLEN + MYSQL_DATABASE_MAXLEN + 2]; snprintf(table_ident, sizeof(table_ident), "%s.%s", map->database.c_str(), map->table.c_str()); + if (!table_matches(table_ident)) + { + return true; + } + bool ok = m_handler->prepare_table(map->database, map->table); auto create = m_created_tables.find(table_ident); @@ -664,8 +675,8 @@ bool Rpl::handle_row_event(REP_HEADER *hdr, uint8_t *ptr) } else { - MXS_ERROR("Row event for unknown table mapped to ID %lu. Data will not " - "be processed.", table_id); + MXS_INFO("Row event for unknown table mapped to ID %lu. Data will not " + "be processed.", table_id); } return rval; diff --git a/server/modules/routing/avrorouter/rpl.cc b/server/modules/routing/avrorouter/rpl.cc index 61b31dce8..38e87818c 100644 --- a/server/modules/routing/avrorouter/rpl.cc +++ b/server/modules/routing/avrorouter/rpl.cc @@ -604,12 +604,17 @@ TableMapEvent *table_map_alloc(uint8_t *ptr, uint8_t hdr_len, TableCreateEvent* std::move(cols), std::move(nulls), std::move(meta)); } -Rpl::Rpl(SERVICE* service, SRowEventHandler handler, gtid_pos_t gtid): +Rpl::Rpl(SERVICE* service, SRowEventHandler handler, pcre2_code* match, pcre2_code* exclude, + gtid_pos_t gtid): m_handler(handler), m_service(service), m_binlog_checksum(0), m_event_types(0), - m_gtid(gtid) + m_gtid(gtid), + m_match(match), + m_exclude(exclude), + m_md_match(m_match ? pcre2_match_data_create_from_pattern(m_match, NULL) : nullptr), + m_md_exclude(m_exclude ? pcre2_match_data_create_from_pattern(m_exclude, NULL) : nullptr) { /** For detection of CREATE/ALTER TABLE statements */ static const char* create_table_regex = "(?i)create[a-z0-9[:space:]_]+table"; @@ -1356,3 +1361,20 @@ bool Rpl::table_create_alter(STableCreateEvent create, const char *sql, const ch return true; } + +bool Rpl::table_matches(const std::string& ident) +{ + bool rval = false; + + if (!m_match || pcre2_match(m_match, (PCRE2_SPTR)ident.c_str(), PCRE2_ZERO_TERMINATED, + 0, 0, m_md_match, NULL) > 0) + { + if (!m_exclude || pcre2_match(m_exclude, (PCRE2_SPTR)ident.c_str(), PCRE2_ZERO_TERMINATED, + 0, 0, m_md_exclude, NULL) == PCRE2_ERROR_NOMATCH) + { + rval = true; + } + } + + return rval; +} diff --git a/server/modules/routing/avrorouter/rpl.hh b/server/modules/routing/avrorouter/rpl.hh index 800071f3c..c7c497133 100644 --- a/server/modules/routing/avrorouter/rpl.hh +++ b/server/modules/routing/avrorouter/rpl.hh @@ -226,7 +226,8 @@ public: Rpl& operator=(const Rpl&) = delete; // Construct a new replication stream transformer - Rpl(SERVICE* service, SRowEventHandler event_handler, gtid_pos_t = {}); + Rpl(SERVICE* service, SRowEventHandler event_handler, pcre2_code* match, pcre2_code* exclude, + gtid_pos_t = {}); // Add a stored TableCreateEvent void add_create(STableCreateEvent create); @@ -256,17 +257,21 @@ public: } private: - SRowEventHandler m_handler; - SERVICE* m_service; - pcre2_code* m_create_table_re; - pcre2_code* m_alter_table_re; - uint8_t m_binlog_checksum; - uint8_t m_event_types; - Bytes m_event_type_hdr_lens; - gtid_pos_t m_gtid; - ActiveMaps m_active_maps; - MappedTables m_table_maps; - CreatedTables m_created_tables; + SRowEventHandler m_handler; + SERVICE* m_service; + pcre2_code* m_create_table_re; + pcre2_code* m_alter_table_re; + uint8_t m_binlog_checksum; + uint8_t m_event_types; + Bytes m_event_type_hdr_lens; + gtid_pos_t m_gtid; + ActiveMaps m_active_maps; + MappedTables m_table_maps; + CreatedTables m_created_tables; + pcre2_code* m_match; + pcre2_code* m_exclude; + pcre2_match_data* m_md_match; + pcre2_match_data* m_md_exclude; void handle_query_event(REP_HEADER *hdr, uint8_t *ptr); bool handle_table_map_event(REP_HEADER *hdr, uint8_t *ptr); @@ -274,4 +279,5 @@ private: STableCreateEvent table_create_copy(const char* sql, size_t len, const char* db); bool save_and_replace_table_create(STableCreateEvent created); bool table_create_alter(STableCreateEvent create, const char *sql, const char *end); + bool table_matches(const std::string& ident); };