From 01cc92e098be51798d80bb8f3e1d61dc47979d63 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sun, 1 Dec 2024 13:52:41 +0400 Subject: [PATCH 01/15] MDEV-34700 Connect SQLite3 MTR test fails due to various charset/collation related output changes Re-recorded test results with the COLLATE clause, according to MDEV-29446. --- storage/connect/mysql-test/connect/r/odbc_sqlite3.result | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result index bce69227073..0a241305a62 100644 --- a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result +++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result @@ -2,14 +2,14 @@ Table Create Table t1 CREATE TABLE `t1` ( `Description` char(128) NOT NULL, `Attributes` varchar(256) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' +) ENGINE=CONNECT DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' SET NAMES utf8; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(64) DEFAULT NULL -) ENGINE=CONNECT DEFAULT CHARSET=utf8 CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' `TABLE_TYPE`='ODBC' `DATA_CHARSET`='utf8' +) ENGINE=CONNECT DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' `TABLE_TYPE`='ODBC' `DATA_CHARSET`='utf8' SELECT * FROM t1; a test1 @@ -21,8 +21,8 @@ CREATE TABLE t2 AS SELECT * FROM t1; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` varchar(64) CHARACTER SET utf8 DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 + `a` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci SELECT * FROM t2; a test1 From ecf2e131bd5f17f8ed97c50cfe8dc13623a763d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 2 Dec 2024 11:04:38 +0200 Subject: [PATCH 02/15] MDEV-31174 fixup: clang++-20 -Wnontrivial-memcall --- sql/item_create.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_create.h b/sql/item_create.h index 25a75a22163..166e173b3c2 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -304,7 +304,7 @@ class Native_functions_hash: public HASH public: Native_functions_hash() { - bzero(this, sizeof(*this)); + bzero((void*) this, sizeof(*this)); } ~Native_functions_hash() { From 3de412fbe884a85b2ec7ae56fee47152c008e6c0 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 19 Nov 2024 12:44:42 +0400 Subject: [PATCH 03/15] MDEV-25593 Assertion `0' failed in Type_handler_temporal_result::Item_get_date on double EXECUTE When binding to NULL, DEFAULT or IGNORE from an Item value, Item_param did not change m_type_handler, so its value remained from the previous bind. Thid led to DBUG_ASSERTs in Item_param::get_date() and Timestamp_or_zero_datetime_native_null. Fix: Set Item_param::m_type_handler to &type_handler_null when binding from an Item returning NULL. This patch also fixes MDEV-35427. --- mysql-test/main/ps_11bugs.result | 55 +++++++++++++++++++ mysql-test/main/ps_11bugs.test | 38 +++++++++++++ .../mysql-test/type_inet/type_inet6_ps.result | 17 ++++++ .../mysql-test/type_inet/type_inet6_ps.test | 16 ++++++ sql/item.cc | 12 +++- sql/item.h | 10 ++-- sql/sql_prepare.cc | 4 +- 7 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 plugin/type_inet/mysql-test/type_inet/type_inet6_ps.result create mode 100644 plugin/type_inet/mysql-test/type_inet/type_inet6_ps.test diff --git a/mysql-test/main/ps_11bugs.result b/mysql-test/main/ps_11bugs.result index 3bc7039583b..87a3487141b 100644 --- a/mysql-test/main/ps_11bugs.result +++ b/mysql-test/main/ps_11bugs.result @@ -191,3 +191,58 @@ Warnings: Warning 1292 Truncated incorrect INTEGER value: '+ -><()~*:""&|' SET @@sort_buffer_size=DEFAULT; End of 5.0 tests. +# Start of 10.5 tests +# +# MDEV-25593 Assertion `0' failed in Type_handler_temporal_result::Item_get_date on double EXECUTE +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30'); +PREPARE stmt FROM 'SELECT ? AS c1'; +EXECUTE stmt USING current_timestamp; +c1 +2001-01-01 10:20:30 +EXECUTE stmt USING @unknown; +c1 +NULL +DEALLOCATE PREPARE stmt; +PREPARE stmt FROM 'SELECT ? AS c1 FROM DUAL'; +EXECUTE stmt USING current_time; +c1 +10:20:30 +EXECUTE stmt USING DEFAULT; +c1 +NULL +DEALLOCATE PREPARE stmt; +PREPARE stmt FROM 'SELECT ? AS c1 FROM DUAL'; +EXECUTE stmt USING current_time; +c1 +10:20:30 +EXECUTE stmt USING IGNORE; +c1 +NULL +DEALLOCATE PREPARE stmt; +PREPARE stmt FROM "SELECT DATE('') between''AND ? AS c1"; +EXECUTE stmt USING current_time; +c1 +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' +EXECUTE stmt USING @unknown; +c1 +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' +DEALLOCATE PREPARE stmt; +PREPARE stmt FROM 'SELECT CONCAT(UNIX_TIMESTAMP(?)) AS c1'; +EXECUTE stmt USING CURRENT_TIMESTAMP; +c1 +978344430 +EXECUTE stmt USING @unknown; +c1 +NULL +DEALLOCATE PREPARE stmt; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# End of 10.5 tests diff --git a/mysql-test/main/ps_11bugs.test b/mysql-test/main/ps_11bugs.test index 1888de060fc..7a0843e9352 100644 --- a/mysql-test/main/ps_11bugs.test +++ b/mysql-test/main/ps_11bugs.test @@ -217,3 +217,41 @@ SELECT LEFT("12345", @@ft_boolean_syntax); SET @@sort_buffer_size=DEFAULT; --echo End of 5.0 tests. + + +--echo # Start of 10.5 tests + +--echo # +--echo # MDEV-25593 Assertion `0' failed in Type_handler_temporal_result::Item_get_date on double EXECUTE +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30'); +PREPARE stmt FROM 'SELECT ? AS c1'; +EXECUTE stmt USING current_timestamp; +EXECUTE stmt USING @unknown; +DEALLOCATE PREPARE stmt; + +PREPARE stmt FROM 'SELECT ? AS c1 FROM DUAL'; +EXECUTE stmt USING current_time; +EXECUTE stmt USING DEFAULT; +DEALLOCATE PREPARE stmt; + +PREPARE stmt FROM 'SELECT ? AS c1 FROM DUAL'; +EXECUTE stmt USING current_time; +EXECUTE stmt USING IGNORE; +DEALLOCATE PREPARE stmt; + +PREPARE stmt FROM "SELECT DATE('') between''AND ? AS c1"; +EXECUTE stmt USING current_time; +EXECUTE stmt USING @unknown; +DEALLOCATE PREPARE stmt; + +PREPARE stmt FROM 'SELECT CONCAT(UNIX_TIMESTAMP(?)) AS c1'; +EXECUTE stmt USING CURRENT_TIMESTAMP; +EXECUTE stmt USING @unknown; +DEALLOCATE PREPARE stmt; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + +--echo # End of 10.5 tests diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_ps.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_ps.result new file mode 100644 index 00000000000..4458f5e2f75 --- /dev/null +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_ps.result @@ -0,0 +1,17 @@ +# Start of 10.5 tests +# +# MDEV-35427 Assertion `is_null() >= item->null_value' failed in Timestamp_or_zero_datetime_native_null::Timestamp_or_zero_datetime_native_null on EXECUTE +# +SET time_zone='+00:00'; +SET timestamp=1000000000; +PREPARE s FROM 'SELECT CONCAT (UNIX_TIMESTAMP(?))'; +EXECUTE s USING CAST('::' AS INET6); +CONCAT (UNIX_TIMESTAMP(?)) +999993600 +EXECUTE s USING NULL; +CONCAT (UNIX_TIMESTAMP(?)) +NULL +DEALLOCATE PREPARE s; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# End of 10.5 tests diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_ps.test b/plugin/type_inet/mysql-test/type_inet/type_inet6_ps.test new file mode 100644 index 00000000000..4251e820e17 --- /dev/null +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_ps.test @@ -0,0 +1,16 @@ +--echo # Start of 10.5 tests + +--echo # +--echo # MDEV-35427 Assertion `is_null() >= item->null_value' failed in Timestamp_or_zero_datetime_native_null::Timestamp_or_zero_datetime_native_null on EXECUTE +--echo # + +SET time_zone='+00:00'; +SET timestamp=1000000000; +PREPARE s FROM 'SELECT CONCAT (UNIX_TIMESTAMP(?))'; +EXECUTE s USING CAST('::' AS INET6); +EXECUTE s USING NULL; +DEALLOCATE PREPARE s; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + +--echo # End of 10.5 tests diff --git a/sql/item.cc b/sql/item.cc index dc27feb759a..dd9a9063e55 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4426,6 +4426,7 @@ bool Item_param::set_from_item(THD *thd, Item *item) if (item->null_value) { set_null(); + set_handler(&type_handler_null); DBUG_RETURN(false); } else @@ -4443,7 +4444,10 @@ bool Item_param::set_from_item(THD *thd, Item *item) DBUG_RETURN(set_value(thd, item, &tmp, h)); } else + { set_null(); + set_handler(&type_handler_null); + } DBUG_RETURN(0); } @@ -4963,7 +4967,7 @@ Item_param::set_param_type_and_swap_value(Item_param *src) } -void Item_param::set_default() +void Item_param::set_default(bool set_type_handler_null) { m_is_settable_routine_parameter= false; state= DEFAULT_VALUE; @@ -4976,13 +4980,17 @@ void Item_param::set_default() can misbehave (e.g. crash on asserts). */ null_value= true; + if (set_type_handler_null) + set_handler(&type_handler_null); } -void Item_param::set_ignore() +void Item_param::set_ignore(bool set_type_handler_null) { m_is_settable_routine_parameter= false; state= IGNORE_VALUE; null_value= true; + if (set_type_handler_null) + set_handler(&type_handler_null); } /** diff --git a/sql/item.h b/sql/item.h index 204f98b7677..8a13c9ea85a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4154,8 +4154,8 @@ public: int save_in_field(Field *field, bool no_conversions) override; - void set_default(); - void set_ignore(); + void set_default(bool set_type_handler_null); + void set_ignore(bool set_type_handler_null); void set_null(); void set_int(longlong i, uint32 max_length_arg); void set_double(double i); @@ -6695,7 +6695,7 @@ public: { // It should not be possible to have "EXECUTE .. USING DEFAULT(a)" DBUG_ASSERT(0); - param->set_default(); + param->set_default(true); return false; } table_map used_tables() const override; @@ -6826,7 +6826,7 @@ public: } bool save_in_param(THD *, Item_param *param) override { - param->set_default(); + param->set_default(true); return false; } Item *do_get_copy(THD *thd) const override @@ -6860,7 +6860,7 @@ public: } bool save_in_param(THD *, Item_param *param) override { - param->set_ignore(); + param->set_ignore(true); return false; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 8647db0e766..3d7dda16643 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -899,10 +899,10 @@ static bool insert_bulk_params(Prepared_statement *stmt, param->set_null(); break; case STMT_INDICATOR_DEFAULT: - param->set_default(); + param->set_default(false); break; case STMT_INDICATOR_IGNORE: - param->set_ignore(); + param->set_ignore(false); break; default: DBUG_ASSERT(0); From 5c86f3df33dc972acfc3665025c25d6430887569 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 29 Nov 2024 11:45:01 +0100 Subject: [PATCH 04/15] MDEV-35522: MariaDB Audit does not detect all DCLs forms when masking password 1. skip OR REPLACE (to make it filter_query_type made recursive) 2. skip SET STATEMENT ... FOR before checking statements with passwords --- .../plugins/r/server_audit_pwd_mask.result | 11 ++ .../plugins/t/server_audit_pwd_mask.test | 13 ++ plugin/server_audit/server_audit.c | 170 ++++++++++++------ 3 files changed, 142 insertions(+), 52 deletions(-) diff --git a/mysql-test/suite/plugins/r/server_audit_pwd_mask.result b/mysql-test/suite/plugins/r/server_audit_pwd_mask.result index 7cf3b05bcf1..ce90230f1ea 100644 --- a/mysql-test/suite/plugins/r/server_audit_pwd_mask.result +++ b/mysql-test/suite/plugins/r/server_audit_pwd_mask.result @@ -1,3 +1,6 @@ +# +# MDEV-35507 and MDEV-35522 +# install plugin ed25519 soname 'auth_ed25519'; install plugin server_audit soname 'server_audit'; set global server_audit_file_path='server_audit.log'; @@ -6,17 +9,25 @@ set global server_audit_logging=on; # unsafe to log passwords (pwd-123) CREATE USER u1 IDENTIFIED BY 'pwd_123'; create user u2 IDENTIFIED VIA ed25519 USING PASSWORD('pwd_123'); +CREATE OR REPLACE USER u1 IDENTIFIED BY 'pwd_123'; SET PASSWORD FOR u1 = PASSWORD('pwd_123'); ALTER USER u1 IDENTIFIED BY 'pwd_123'; +ALTER USER if exists u1 IDENTIFIED BY 'pwd_123'; +SET STATEMENT max_statement_time=10 FOR ALTER USER u1 IDENTIFIED BY 'pwd_123'; alter user u2 identified VIA ed25519 USING password('pwd_123'); GRANT ALL ON test TO u1 IDENTIFIED BY "pwd_123"; GRANT ALL ON test TO u1 identified VIA ed25519 as password('pwd_123') or ed25519 using password('pwd_123'); +CREATE SERVER s1 FOREIGN DATA WRAPPER mariadb OPTIONS ( PASSWORD "pwd_123"); +CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mariadb OPTIONS ( PASSWORD "pwd_123"); +CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mariadb OPTIONS ( PASSWORD "pwd_123"); # pattern should not be found NOT FOUND /pwd_123/ in server_audit.log # pattern should not be found # cleaunup +DROP SERVER s1; DROP USER u1; DROP USER u2; set global server_audit_logging=off; UNINSTALL PLUGIN ed25519; UNINSTALL PLUGIN server_audit; +# end of 10.5 tests diff --git a/mysql-test/suite/plugins/t/server_audit_pwd_mask.test b/mysql-test/suite/plugins/t/server_audit_pwd_mask.test index af6425b2035..b393e22d11e 100644 --- a/mysql-test/suite/plugins/t/server_audit_pwd_mask.test +++ b/mysql-test/suite/plugins/t/server_audit_pwd_mask.test @@ -13,6 +13,10 @@ if (!$AUTH_ED25519_SO) { let $MYSQLD_DATADIR= `SELECT @@datadir`; let SEARCH_FILE= $MYSQLD_DATADIR/server_audit.log; +--echo # +--echo # MDEV-35507 and MDEV-35522 +--echo # + install plugin ed25519 soname 'auth_ed25519'; install plugin server_audit soname 'server_audit'; @@ -25,17 +29,24 @@ set global server_audit_logging=on; CREATE USER u1 IDENTIFIED BY 'pwd_123'; create user u2 IDENTIFIED VIA ed25519 USING PASSWORD('pwd_123'); +CREATE OR REPLACE USER u1 IDENTIFIED BY 'pwd_123'; SET PASSWORD FOR u1 = PASSWORD('pwd_123'); ALTER USER u1 IDENTIFIED BY 'pwd_123'; +ALTER USER if exists u1 IDENTIFIED BY 'pwd_123'; +SET STATEMENT max_statement_time=10 FOR ALTER USER u1 IDENTIFIED BY 'pwd_123'; alter user u2 identified VIA ed25519 USING password('pwd_123'); GRANT ALL ON test TO u1 IDENTIFIED BY "pwd_123"; GRANT ALL ON test TO u1 identified VIA ed25519 as password('pwd_123') or ed25519 using password('pwd_123'); +CREATE SERVER s1 FOREIGN DATA WRAPPER mariadb OPTIONS ( PASSWORD "pwd_123"); +CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mariadb OPTIONS ( PASSWORD "pwd_123"); +CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mariadb OPTIONS ( PASSWORD "pwd_123"); --let SEARCH_PATTERN=pwd_123 --echo # pattern should not be found --source include/search_pattern_in_file.inc --echo # pattern should not be found --echo # cleaunup +DROP SERVER s1; DROP USER u1; DROP USER u2; set global server_audit_logging=off; @@ -44,3 +55,5 @@ set global server_audit_logging=off; UNINSTALL PLUGIN ed25519; UNINSTALL PLUGIN server_audit; --enable_warnings + +--echo # end of 10.5 tests diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 2de27215ed9..0f1a53183a3 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -818,6 +818,7 @@ enum sa_keywords SQLCOM_TRUNCATE, SQLCOM_QUERY_ADMIN, SQLCOM_DCL, + SQLCOM_FOUND=-1, }; struct sa_keyword @@ -829,30 +830,87 @@ struct sa_keyword }; -struct sa_keyword xml_word= {3, "XML", 0, SQLCOM_NOTHING}; -struct sa_keyword user_word= {4, "USER", 0, SQLCOM_NOTHING}; -struct sa_keyword data_word= {4, "DATA", 0, SQLCOM_NOTHING}; -struct sa_keyword server_word= {6, "SERVER", 0, SQLCOM_NOTHING}; -struct sa_keyword master_word= {6, "MASTER", 0, SQLCOM_NOTHING}; -struct sa_keyword password_word= {8, "PASSWORD", 0, SQLCOM_NOTHING}; -struct sa_keyword function_word= {8, "FUNCTION", 0, SQLCOM_NOTHING}; -struct sa_keyword statement_word= {9, "STATEMENT", 0, SQLCOM_NOTHING}; -struct sa_keyword procedure_word= {9, "PROCEDURE", 0, SQLCOM_NOTHING}; +struct sa_keyword xml_word[]= +{ + {3, "XML", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword user_word[]= +{ + {4, "USER", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword data_word[]= +{ + {4, "DATA", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword server_word[]= +{ + {6, "SERVER", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword master_word[]= +{ + {6, "MASTER", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword password_word[]= +{ + {8, "PASSWORD", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword function_word[]= +{ + {8, "FUNCTION", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword statement_word[]= +{ + {9, "STATEMENT", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword procedure_word[]= +{ + {9, "PROCEDURE", 0, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword replace_user_word[]= +{ + {7, "REPLACE", user_word, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword or_replace_user_word[]= +{ + {2, "OR", replace_user_word, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword replace_server_word[]= +{ + {7, "REPLACE", server_word, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; +struct sa_keyword or_replace_server_word[]= +{ + {2, "OR", replace_server_word, SQLCOM_FOUND}, + {0, NULL, 0, SQLCOM_NOTHING} +}; struct sa_keyword keywords_to_skip[]= { - {3, "SET", &statement_word, SQLCOM_QUERY_ADMIN}, - {0, NULL, 0, SQLCOM_DDL} + {3, "SET", statement_word, SQLCOM_QUERY_ADMIN}, + {0, NULL, 0, SQLCOM_NOTHING} }; struct sa_keyword not_ddl_keywords[]= { - {4, "DROP", &user_word, SQLCOM_DCL}, - {6, "CREATE", &user_word, SQLCOM_DCL}, - {6, "RENAME", &user_word, SQLCOM_DCL}, - {0, NULL, 0, SQLCOM_DDL} + {4, "DROP", user_word, SQLCOM_DCL}, + {6, "CREATE", user_word, SQLCOM_DCL}, + {6, "CREATE", or_replace_user_word, SQLCOM_DCL}, + {6, "RENAME", user_word, SQLCOM_DCL}, + {0, NULL, 0, SQLCOM_NOTHING} }; @@ -863,7 +921,7 @@ struct sa_keyword ddl_keywords[]= {6, "CREATE", 0, SQLCOM_DDL}, {6, "RENAME", 0, SQLCOM_DDL}, {8, "TRUNCATE", 0, SQLCOM_DDL}, - {0, NULL, 0, SQLCOM_DDL} + {0, NULL, 0, SQLCOM_NOTHING} }; @@ -871,15 +929,15 @@ struct sa_keyword dml_keywords[]= { {2, "DO", 0, SQLCOM_DML}, {4, "CALL", 0, SQLCOM_DML}, - {4, "LOAD", &data_word, SQLCOM_DML}, - {4, "LOAD", &xml_word, SQLCOM_DML}, + {4, "LOAD", data_word, SQLCOM_DML}, + {4, "LOAD", xml_word, SQLCOM_DML}, {6, "DELETE", 0, SQLCOM_DML}, {6, "INSERT", 0, SQLCOM_DML}, {6, "SELECT", 0, SQLCOM_DML}, {6, "UPDATE", 0, SQLCOM_DML}, {7, "HANDLER", 0, SQLCOM_DML}, {7, "REPLACE", 0, SQLCOM_DML}, - {0, NULL, 0, SQLCOM_DML} + {0, NULL, 0, SQLCOM_NOTHING} }; @@ -887,38 +945,41 @@ struct sa_keyword dml_no_select_keywords[]= { {2, "DO", 0, SQLCOM_DML}, {4, "CALL", 0, SQLCOM_DML}, - {4, "LOAD", &data_word, SQLCOM_DML}, - {4, "LOAD", &xml_word, SQLCOM_DML}, + {4, "LOAD", data_word, SQLCOM_DML}, + {4, "LOAD", xml_word, SQLCOM_DML}, {6, "DELETE", 0, SQLCOM_DML}, {6, "INSERT", 0, SQLCOM_DML}, {6, "UPDATE", 0, SQLCOM_DML}, {7, "HANDLER", 0, SQLCOM_DML}, {7, "REPLACE", 0, SQLCOM_DML}, - {0, NULL, 0, SQLCOM_DML} + {0, NULL, 0, SQLCOM_NOTHING} }; struct sa_keyword dcl_keywords[]= { - {6, "CREATE", &user_word, SQLCOM_DCL}, - {4, "DROP", &user_word, SQLCOM_DCL}, - {6, "RENAME", &user_word, SQLCOM_DCL}, + {6, "CREATE", user_word, SQLCOM_DCL}, + {6, "CREATE", or_replace_user_word, SQLCOM_DCL}, + {4, "DROP", user_word, SQLCOM_DCL}, + {6, "RENAME", user_word, SQLCOM_DCL}, {5, "GRANT", 0, SQLCOM_DCL}, {6, "REVOKE", 0, SQLCOM_DCL}, - {3, "SET", &password_word, SQLCOM_DCL}, - {0, NULL, 0, SQLCOM_DDL} + {3, "SET", password_word, SQLCOM_DCL}, + {0, NULL, 0, SQLCOM_NOTHING} }; struct sa_keyword passwd_keywords[]= { - {3, "SET", &password_word, SQLCOM_SET_OPTION}, - {5, "ALTER", &server_word, SQLCOM_ALTER_SERVER}, - {5, "ALTER", &user_word, SQLCOM_ALTER_USER}, + {3, "SET", password_word, SQLCOM_SET_OPTION}, + {5, "ALTER", server_word, SQLCOM_ALTER_SERVER}, + {5, "ALTER", user_word, SQLCOM_ALTER_USER}, {5, "GRANT", 0, SQLCOM_GRANT}, - {6, "CREATE", &user_word, SQLCOM_CREATE_USER}, - {6, "CREATE", &server_word, SQLCOM_CREATE_SERVER}, - {6, "CHANGE", &master_word, SQLCOM_CHANGE_MASTER}, + {6, "CREATE", user_word, SQLCOM_CREATE_USER}, + {6, "CREATE", or_replace_user_word, SQLCOM_CREATE_USER}, + {6, "CREATE", server_word, SQLCOM_CREATE_SERVER}, + {6, "CREATE", or_replace_server_word, SQLCOM_CREATE_SERVER}, + {6, "CHANGE", master_word, SQLCOM_CHANGE_MASTER}, {0, NULL, 0, SQLCOM_NOTHING} }; @@ -1732,7 +1793,7 @@ static int filter_query_type(const char *query, struct sa_keyword *kwd) query++; } - qwe_in_list= 0; + qwe_in_list= SQLCOM_NOTHING; if (!(len= get_next_word(query, fword))) goto not_in_list; query+= len+1; @@ -1750,8 +1811,7 @@ static int filter_query_type(const char *query, struct sa_keyword *kwd) query++; nlen= get_next_word(query, nword); } - if (l_keywords->next->length != nlen || - strncmp(l_keywords->next->wd, nword, nlen) != 0) + if (filter_query_type(query, l_keywords->next) == SQLCOM_NOTHING) goto do_loop; } @@ -1766,6 +1826,25 @@ not_in_list: return qwe_in_list; } +static const char *skip_set_statement(const char *query) +{ + if (filter_query_type(query, keywords_to_skip)) + { + char fword[MAX_KEYWORD + 1]; + int len; + do + { + len= get_next_word(query, fword); + query+= len ? len : 1; + if (len == 3 && strncmp(fword, "FOR", 3) == 0) + break; + } while (*query); + + if (*query == 0) + return 0; + } + return query; +} static int log_statement_ex(const struct connection_info *cn, time_t ev_time, unsigned long thd_id, @@ -1809,21 +1888,8 @@ static int log_statement_ex(const struct connection_info *cn, { const char *orig_query= query; - if (filter_query_type(query, keywords_to_skip)) - { - char fword[MAX_KEYWORD + 1]; - int len; - do - { - len= get_next_word(query, fword); - query+= len ? len : 1; - if (len == 3 && strncmp(fword, "FOR", 3) == 0) - break; - } while (*query); - - if (*query == 0) - return 0; - } + if ((query= skip_set_statement(query)) == SQLCOM_NOTHING) + return 0; if (events & EVENT_QUERY_DDL) { @@ -1879,7 +1945,7 @@ do_log_query: if (query_log_limit > 0 && uh_buffer_size > query_log_limit+2) uh_buffer_size= query_log_limit+2; - switch (filter_query_type(query, passwd_keywords)) + switch (filter_query_type(skip_set_statement(query), passwd_keywords)) { case SQLCOM_GRANT: case SQLCOM_CREATE_USER: From d0fcac44501b93593219ef2210032d06458d5410 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 29 Nov 2024 11:12:10 +1100 Subject: [PATCH 05/15] MDEV-35422 Fix spider group by handler trying to use fake group by fields This is a fixup of MDEV-26345 commit 77ed235d50bd9b1480f26d18ea0b70ca7480af23. In MDEV-26345 the spider group by handler was updated so that it uses the item_ptr fields of Query::group_by and Query::order_by, instead of item. This was and is because the call to join->set_items_ref_array(join->items1) during the execution stage, just before the execution replaces the order-by / group-by item arrays with Item_temptable_field. Spider traverses the item tree during the group by handler (gbh) creation at the end of the optimization stage, and decides a gbh could handle the execution of the query. Basically spider gbh can handle the execution if it can construct a well-formed query, executes on the data node, and store the results in the correct places. If so, it will create one, otherwise it will return NULL and the execution will use the usual handler (ha_spider instead of spider_group_by_handler). To that end, the general principle is the items checked for creation should be the same items later used for query construciton. Since in MDEV-26345 we changed to use the item_ptr field instead of item field of order-by and group-by in query construction, in this patch we do the same for the gbh creation. The item_ptr field could be the uninitialised NULL value during the gbh creation. This is because the optimizer may replace a DISTINCT with a GROUP BY, which only happens if the original GROUP BY is empty. It creates the artificial GROUP BY by calling create_distinct_group(), which creates the corresponding ORDER object with item field aligning with somewhere in ref_pointer_array, but leaving item_ptr to be NULL. When spider finds out that item_ptr is NULL, it knows there's some optimizer skullduggery and it is passed a query different from the original. Without a clear contract between the server layer and the gbh, it is better to be safe than sorry and not create the gbh in this case. Also add a check and error reporting for the unlikely case of item_ptr changing from non-NULL at gbh construction to NULL at execution to prevent server crash. Also, we remove a check added in MDEV-29480 of order by items being aggregate functions. That check was added with the premise that spider was including auxiliary SELECT items which is referenced by ORDER BY items. This premise was no longer true since MDEV-26345, and caused problems such as MDEV-29546, which was fixed by MDEV-26345. --- .../spider/bugfix/r/mdev_34659.result | 7 ++++++ .../spider/bugfix/r/mdev_35422.result | 24 +++++++++++++++++++ .../spider/bugfix/t/mdev_34659.test | 2 ++ .../spider/bugfix/t/mdev_35422.test | 21 ++++++++++++++++ storage/spider/spd_db_mysql.cc | 24 +++++++++++++++++++ storage/spider/spd_group_by_handler.cc | 14 ++++++----- 6 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_35422.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_35422.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_34659.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_34659.result index e77939396b0..e0f8b25d3c1 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_34659.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_34659.result @@ -16,6 +16,13 @@ SELECT * FROM t2 ORDER BY CAST(c AS INET6); c 456 123 +SELECT * FROM t2 GROUP BY CAST(c AS char(60)); +c +123 +456 +SELECT * FROM t2 GROUP BY CAST(c AS INET6); +c +456 DROP TABLE t1,t2; drop server srv; for master_1 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_35422.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_35422.result new file mode 100644 index 00000000000..1d19fe84cac --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_35422.result @@ -0,0 +1,24 @@ +for master_1 +for child2 +for child3 +set spider_same_server_link= 1; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c varchar(10)); +create table t1 (c varchar(10)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values ('abc'), ('abd'), ('abcd'), ('abc'); +SELECT DISTINCT c FROM t1; +c +abc +abd +abcd +SELECT DISTINCT c FROM t1 WHERE (c LIKE 'abc%'); +c +abc +abcd +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_34659.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_34659.test index 3b481d2277f..3b1dc206866 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_34659.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_34659.test @@ -13,6 +13,8 @@ CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE " insert into t2 values (456), (123); SELECT * FROM t2 ORDER BY CAST(c AS char(60)); SELECT * FROM t2 ORDER BY CAST(c AS INET6); +SELECT * FROM t2 GROUP BY CAST(c AS char(60)); +SELECT * FROM t2 GROUP BY CAST(c AS INET6); # Cleanup DROP TABLE t1,t2; drop server srv; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_35422.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_35422.test new file mode 100644 index 00000000000..dc89bc88edc --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_35422.test @@ -0,0 +1,21 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c varchar(10)); +create table t1 (c varchar(10)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values ('abc'), ('abd'), ('abcd'), ('abc'); +SELECT DISTINCT c FROM t1; +SELECT DISTINCT c FROM t1 WHERE (c LIKE 'abc%'); +drop table t1, t2; +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 4b232c18166..5fd215de341 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -14066,6 +14066,11 @@ int spider_mbase_handler::append_group_by_part( DBUG_RETURN(error_num); } +/* + Append the GROUP BY part. + + Only used by the group by handler for query construction. +*/ int spider_mbase_handler::append_group_by( ORDER *order, spider_string *str, @@ -14084,6 +14089,13 @@ int spider_mbase_handler::append_group_by( str->q_append(SPIDER_SQL_GROUP_STR, SPIDER_SQL_GROUP_LEN); for (; order; order = order->next) { + /* + This is not expected to happen, as NULL check was performed + at the creation of the group by handler, and any NULL item_ptr + would have resulted in the gbh not being created. + */ + if (!order->item_ptr) + DBUG_RETURN(ER_INTERNAL_ERROR); if ((error_num = spider_db_print_item_type(order->item_ptr, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { @@ -14123,6 +14135,11 @@ int spider_mbase_handler::append_order_by_part( DBUG_RETURN(error_num); } +/* + Append the ORDER BY part. + + Only used by the group by handler for query construction. +*/ int spider_mbase_handler::append_order_by( ORDER *order, spider_string *str, @@ -14141,6 +14158,13 @@ int spider_mbase_handler::append_order_by( str->q_append(SPIDER_SQL_ORDER_STR, SPIDER_SQL_ORDER_LEN); for (; order; order = order->next) { + /* + This is not expected to happen, as NULL check was performed + at the creation of the group by handler, and any NULL item_ptr + would have resulted in the gbh not being created. + */ + if (!order->item_ptr) + DBUG_RETURN(ER_INTERNAL_ERROR); if ((error_num = spider_db_print_item_type(order->item_ptr, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index e90129e6113..0c62e6cf7eb 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -1622,8 +1622,10 @@ group_by_handler *spider_create_group_by_handler( { for (order = query->group_by; order; order = order->next) { - if (spider_db_print_item_type((*order->item), NULL, spider, NULL, NULL, 0, - roop_count, TRUE, fields_arg)) + if (order->item_ptr == NULL || + spider_db_print_item_type(order->item_ptr, NULL, spider, + NULL, NULL, 0, roop_count, TRUE, + fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create group by", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); @@ -1640,10 +1642,10 @@ group_by_handler *spider_create_group_by_handler( { for (order = query->order_by; order; order = order->next) { - if ((*order->item)->type() == Item::SUM_FUNC_ITEM) - continue; - if (spider_db_print_item_type((*order->item), NULL, spider, NULL, NULL, 0, - roop_count, TRUE, fields_arg)) + if (order->item_ptr == NULL || + spider_db_print_item_type(order->item_ptr, NULL, spider, + NULL, NULL, 0, roop_count, TRUE, + fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create order by", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); From bf3e16eb817cf16e8a9d4a606b54930b67eccd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 21 Nov 2024 12:23:31 +0200 Subject: [PATCH 06/15] MDEV-35467 : WSREP: read_completion_condition(): shutdown while in init () Ignore expected warning from Galera library when connections are shutdown. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/galera_wan.result | 7 +++++++ mysql-test/suite/galera/t/galera_wan.test | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/mysql-test/suite/galera/r/galera_wan.result b/mysql-test/suite/galera/r/galera_wan.result index 21cd5258590..3904c1dc517 100644 --- a/mysql-test/suite/galera/r/galera_wan.result +++ b/mysql-test/suite/galera/r/galera_wan.result @@ -35,3 +35,10 @@ SELECT VARIABLE_VALUE LIKE '%gmcast.segment = 3%' FROM INFORMATION_SCHEMA.GLOBAL VARIABLE_VALUE LIKE '%gmcast.segment = 3%' 1 DROP TABLE t1; +connection node_1; +call mtr.add_suppression("WSREP: read_completion_condition.*"); +call mtr.add_suppression("WSREP: read_handler.*"); +disconnect node_3; +disconnect node_4; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/galera_wan.test b/mysql-test/suite/galera/t/galera_wan.test index 73be33fa33d..ab2346ebe94 100644 --- a/mysql-test/suite/galera/t/galera_wan.test +++ b/mysql-test/suite/galera/t/galera_wan.test @@ -40,3 +40,12 @@ SELECT COUNT(*) AS EXPECT_1 FROM t1; SELECT VARIABLE_VALUE LIKE '%gmcast.segment = 3%' FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'; DROP TABLE t1; + +--connection node_1 +call mtr.add_suppression("WSREP: read_completion_condition.*"); +call mtr.add_suppression("WSREP: read_handler.*"); + +--disconnect node_3 +--disconnect node_4 + +--source include/galera_end.inc From af50783fcd3b8c9b6278dfbcee3d1ecfcbbb8ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 21 Nov 2024 13:22:49 +0200 Subject: [PATCH 07/15] MDEV-35471 : Sporadic failures in the galera_pc_recovery mtr test For some reason InnoDB was disabled at --wsrep-recover call. Added --loose-innodb to command like to make sure InnoDB is enabled. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/disabled.def | 1 - mysql-test/suite/galera/t/galera_pc_recovery.test | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 759fc38be74..16aaf89259f 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -10,7 +10,6 @@ # ############################################################################## -galera_pc_recovery : MDEV-25199 cluster fails to start up galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED galera_concurrent_ctas : MDEV-32779 galera_concurrent_ctas: assertion in the galera::ReplicatorSMM::finish_cert() galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() diff --git a/mysql-test/suite/galera/t/galera_pc_recovery.test b/mysql-test/suite/galera/t/galera_pc_recovery.test index 0fd9c8ab3d9..4489db63a91 100644 --- a/mysql-test/suite/galera/t/galera_pc_recovery.test +++ b/mysql-test/suite/galera/t/galera_pc_recovery.test @@ -33,8 +33,8 @@ SELECT COUNT(*) = 1 FROM t1; # Perform --wsrep-recover and preserve the positions into variables by placing them in $MYSQL_TMP_DIR/galera_wsrep_start_position.inc and then --source'ing it ---exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.1.log > $MYSQL_TMP_DIR/galera_wsrep_recover.1.log 2>&1 ---exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.2.log > $MYSQL_TMP_DIR/galera_wsrep_recover.2.log 2>&1 +--exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --loose-innodb --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.1.log > $MYSQL_TMP_DIR/galera_wsrep_recover.1.log 2>&1 +--exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --loose-innodb --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.2.log > $MYSQL_TMP_DIR/galera_wsrep_recover.2.log 2>&1 --perl use strict; From f219fb84893e9837ce09a8811929650347aea4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 7 Nov 2024 09:04:16 +0200 Subject: [PATCH 08/15] MDEV-35355 : Galera test failure on galera_sr.mysql-wsrep-features#165 Problem was that in DeadlockChecker::trx_rollback() we hold lock_sys before we call wsrep_handle_SR_rollback() where THD::LOCK_thd_data (and some cases THD::LOCK_thd_kill) are acquired. This is against current mutex ordering rules. However, acquiring THD::LOCK_thd_data is not necessary because we always are in victim_thd context, either client session is rolling back or rollbacker thread should be in control. Therefore, we should always use wsrep_thd_self_abort() and then no additional mutexes are required. Fixed by removing locking of THD::LOCK_thd_data and using only wsrep_thd_self_abort(). In debug builds added assertions to verify that we are always in victim_thd context. This fix is for MariaDB 10.5 and we already have a test case that sporadically fail in Jenkins before this fix. Signed-off-by: Julius Goryavsky --- sql/service_wsrep.cc | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index c131e3c7fb5..6aab1bec99b 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -186,42 +186,29 @@ extern "C" my_bool wsrep_thd_is_SR(const THD *thd) return thd && thd->wsrep_cs().transaction().is_streaming(); } -extern "C" void wsrep_handle_SR_rollback(THD *bf_thd, +extern "C" void wsrep_handle_SR_rollback(THD *bf_thd __attribute__((unused)), THD *victim_thd) { + /* + We should always be in victim_thd context, either client session is + rolling back or rollbacker thread should be in control. + */ DBUG_ASSERT(victim_thd); + DBUG_ASSERT(current_thd == victim_thd); DBUG_ASSERT(wsrep_thd_is_SR(victim_thd)); - if (!victim_thd || !wsrep_on(bf_thd)) return; - wsrep_thd_LOCK(victim_thd); + /* Defensive measure to avoid crash in production. */ + if (!victim_thd) return; - WSREP_DEBUG("handle rollback, for deadlock: thd %llu trx_id %" PRIu64 " frags %zu conf %s", + WSREP_DEBUG("Handle SR rollback, for deadlock: thd %llu trx_id %" PRIu64 " frags %zu conf %s", victim_thd->thread_id, victim_thd->wsrep_trx_id(), victim_thd->wsrep_sr().fragments_certified(), wsrep_thd_transaction_state_str(victim_thd)); - /* Note: do not store/reset globals before wsrep_bf_abort() call - to avoid losing BF thd context. */ - if (!(bf_thd && bf_thd != victim_thd)) - { - DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback"); - } - if (bf_thd) - { - wsrep_bf_abort(bf_thd, victim_thd); - } - else - { - wsrep_thd_self_abort(victim_thd); - } + DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback"); - wsrep_thd_UNLOCK(victim_thd); - - if (bf_thd) - { - wsrep_store_threadvars(bf_thd); - } + wsrep_thd_self_abort(victim_thd); } extern "C" my_bool wsrep_thd_bf_abort(THD *bf_thd, THD *victim_thd, From 8a32ae5d6dfc9b6f7c97fe76fcaf1f2d6f510168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 5 Nov 2024 09:24:09 +0200 Subject: [PATCH 09/15] MDEV-32779 : galera_concurrent_ctas: assertion in the galera::ReplicatorSMM::finish_cert() I could not reproduce reported assertion. However, I could reporoduce test failure because missing wait_condition and error in test case. Added missing wait_condition and fixed error in test case to make test stable. Signed-off-by: Julius Goryavsky --- .../galera/r/galera_concurrent_ctas.result | 17 +++++++++++++++++ .../t/galera_concurrent_ctas.combinations | 4 ++++ .../suite/galera/t/galera_concurrent_ctas.test | 17 ++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/t/galera_concurrent_ctas.combinations diff --git a/mysql-test/suite/galera/r/galera_concurrent_ctas.result b/mysql-test/suite/galera/r/galera_concurrent_ctas.result index 933f1d2a98e..a25e367bf74 100644 --- a/mysql-test/suite/galera/r/galera_concurrent_ctas.result +++ b/mysql-test/suite/galera/r/galera_concurrent_ctas.result @@ -3,6 +3,7 @@ connection node_1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_1; SET DEBUG_SYNC = 'wsrep_create_table_as_select WAIT_FOR continue'; CREATE table t1 as SELECT SLEEP(0.1);; @@ -17,14 +18,30 @@ connection node_1b; SET SESSION debug_sync = 'now WAIT_FOR sync.wsrep_apply_cb_reached'; # Signal first CTAS to continue and wait until CTAS has executed SET DEBUG_SYNC= 'now SIGNAL continue'; +connection node_2b; +# Wait first CTAS to replicate +SELECT * FROM t1; +SLEEP(0.2) +0 +connection node_1b; SET GLOBAL debug_dbug= ''; SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; connection node_2a; connection node_1b; SET DEBUG_SYNC= 'RESET'; connection node_2; +SELECT * FROM t1; +SLEEP(0.2) +0 connection node_1; +SELECT * FROM t1; +SLEEP(0.2) +0 DROP TABLE t1; +disconnect node_1a; +disconnect node_1b; +disconnect node_2a; +disconnect node_2b; disconnect node_2; disconnect node_1; # End of test diff --git a/mysql-test/suite/galera/t/galera_concurrent_ctas.combinations b/mysql-test/suite/galera/t/galera_concurrent_ctas.combinations new file mode 100644 index 00000000000..1eeb8fb4614 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_concurrent_ctas.combinations @@ -0,0 +1,4 @@ +[binlogoff] + +[binlogon] +log-bin diff --git a/mysql-test/suite/galera/t/galera_concurrent_ctas.test b/mysql-test/suite/galera/t/galera_concurrent_ctas.test index e22ac811c8b..ed579f19a0d 100644 --- a/mysql-test/suite/galera/t/galera_concurrent_ctas.test +++ b/mysql-test/suite/galera/t/galera_concurrent_ctas.test @@ -9,6 +9,7 @@ --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 --connection node_1 # @@ -48,6 +49,14 @@ SET SESSION debug_sync = 'now WAIT_FOR sync.wsrep_apply_cb_reached'; SET DEBUG_SYNC= 'now SIGNAL continue'; --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Creating table CREATE table t1 as SELECT SLEEP(0.1)' --source include/wait_condition.inc + +--connection node_2b +--echo # Wait first CTAS to replicate +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc +SELECT * FROM t1; + +--connection node_1b # # Release second CTAS and cleanup # @@ -74,12 +83,18 @@ SET DEBUG_SYNC= 'RESET'; # --connection node_2 --reap +SELECT * FROM t1; --connection node_1 ---error 0,ER_TABLE_EXISTS_ERROR,ER_QUERY_INTERRUPTED +--error 0,ER_QUERY_INTERRUPTED,ER_LOCK_DEADLOCK --reap +SELECT * FROM t1; DROP TABLE t1; +--disconnect node_1a +--disconnect node_1b +--disconnect node_2a +--disconnect node_2b --source include/galera_end.inc --echo # End of test From c20f09ddcfc5136664b71ddab37f5a1496cf54cf Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 3 Dec 2024 13:49:42 +0300 Subject: [PATCH 10/15] Dtrace cmake fix for clang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When there are GCC-incompatible compiler flags dtrace fails like this: gcc: error: unrecognized command-line option ‘-fno-limit-debug-info’ gcc: error: unrecognized command-line option ‘-mbranches-within-32B-boundaries’ "gcc .dtrace-temp.3fd6bacf.c" failed Usage /usr/bin/dtrace [--help] [-h | -G] [-C [-I]] -s File.d [-o ] --- cmake/dtrace.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmake/dtrace.cmake b/cmake/dtrace.cmake index dae3b56b584..9d3d3cd50c5 100644 --- a/cmake/dtrace.cmake +++ b/cmake/dtrace.cmake @@ -125,16 +125,20 @@ FUNCTION(DTRACE_INSTRUMENT target) WORKING_DIRECTORY ${objdir} ) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") - # dtrace on Linux runs gcc and uses flags from environment - SET(CFLAGS_SAVED $ENV{CFLAGS}) - SET(ENV{CFLAGS} ${CMAKE_C_FLAGS}) + IF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # dtrace on Linux runs gcc and uses flags from environment + SET(CFLAGS_SAVED $ENV{CFLAGS}) + SET(ENV{CFLAGS} ${CMAKE_C_FLAGS}) + ENDIF() SET(outfile "${CMAKE_BINARY_DIR}/probes_mysql.o") # Systemtap object EXECUTE_PROCESS( COMMAND ${DTRACE} -G -s ${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base -o ${outfile} ) - SET(ENV{CFLAGS} ${CFLAGS_SAVED}) + IF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + SET(ENV{CFLAGS} ${CFLAGS_SAVED}) + ENDIF() ENDIF() # Do not try to extend the library if we have not built the .o file From 3835437eb8155740040340c214dbdd0979951b37 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 3 Dec 2024 13:49:42 +0300 Subject: [PATCH 11/15] MDEV-15330 Cleanup: load_data.test removed --- .../suite/versioning/r/load_data.result | 10 ------- mysql-test/suite/versioning/r/replace.result | 11 ++++++++ mysql-test/suite/versioning/t/load_data.test | 16 ----------- mysql-test/suite/versioning/t/replace.test | 28 +++++++++++++++++++ 4 files changed, 39 insertions(+), 26 deletions(-) delete mode 100644 mysql-test/suite/versioning/r/load_data.result delete mode 100644 mysql-test/suite/versioning/t/load_data.test diff --git a/mysql-test/suite/versioning/r/load_data.result b/mysql-test/suite/versioning/r/load_data.result deleted file mode 100644 index 1fcde73e565..00000000000 --- a/mysql-test/suite/versioning/r/load_data.result +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE t1 (a INT, b INT, c INT, vc INT AS (c), UNIQUE(a), UNIQUE(b)) WITH SYSTEM VERSIONING; -INSERT IGNORE INTO t1 (a,b,c) VALUES (1,2,3); -SELECT a, b, c FROM t1 INTO OUTFILE '15330.data'; -Warnings: -Warning 1287 ' INTO FROM...' instead -LOAD DATA INFILE '15330.data' IGNORE INTO TABLE t1 (a,b,c); -Warnings: -Warning 1062 Duplicate entry '1' for key 'a' -LOAD DATA INFILE '15330.data' REPLACE INTO TABLE t1 (a,b,c); -DROP TABLE t1; diff --git a/mysql-test/suite/versioning/r/replace.result b/mysql-test/suite/versioning/r/replace.result index 57a992cce49..8ac4047c5ff 100644 --- a/mysql-test/suite/versioning/r/replace.result +++ b/mysql-test/suite/versioning/r/replace.result @@ -61,3 +61,14 @@ connection con1; replace into t1 values (1),(2); ERROR 23000: Duplicate entry '1' for key 'PRIMARY' drop table t1; +# +# MDEV-15330 Server crash or assertion `table->insert_values' failure in write_record upon LOAD DATA +# +create table t1 (a int, b int, c int, vc int as (c), unique(a), unique(b)) with system versioning; +insert ignore into t1 (a,b,c) values (1,2,3); +select a, b, c into outfile '15330.data' from t1; +load data infile '15330.data' ignore into table t1 (a,b,c); +Warnings: +Warning 1062 Duplicate entry '1' for key 'a' +load data infile '15330.data' replace into table t1 (a,b,c); +drop table t1; diff --git a/mysql-test/suite/versioning/t/load_data.test b/mysql-test/suite/versioning/t/load_data.test deleted file mode 100644 index aa4e2192113..00000000000 --- a/mysql-test/suite/versioning/t/load_data.test +++ /dev/null @@ -1,16 +0,0 @@ -# -# MDEV-15330 Server crash or assertion `table->insert_values' failure in write_record upon LOAD DATA -# -CREATE TABLE t1 (a INT, b INT, c INT, vc INT AS (c), UNIQUE(a), UNIQUE(b)) WITH SYSTEM VERSIONING; -INSERT IGNORE INTO t1 (a,b,c) VALUES (1,2,3); - ---disable_cursor_protocol ---disable_ps2_protocol -SELECT a, b, c FROM t1 INTO OUTFILE '15330.data'; ---enable_ps2_protocol ---enable_cursor_protocol -LOAD DATA INFILE '15330.data' IGNORE INTO TABLE t1 (a,b,c); -LOAD DATA INFILE '15330.data' REPLACE INTO TABLE t1 (a,b,c); - -# Cleanup -DROP TABLE t1; diff --git a/mysql-test/suite/versioning/t/replace.test b/mysql-test/suite/versioning/t/replace.test index 83489f4a4b9..d69eebd1b9c 100644 --- a/mysql-test/suite/versioning/t/replace.test +++ b/mysql-test/suite/versioning/t/replace.test @@ -77,4 +77,32 @@ replace into t1 values (1),(2); drop table t1; +--echo # +--echo # MDEV-15330 Server crash or assertion `table->insert_values' failure in write_record upon LOAD DATA +--echo # +if ($default_engine == MEMORY) +{ + --disable_query_log + set default_storage_engine= myisam; + --enable_query_log +} +create table t1 (a int, b int, c int, vc int as (c), unique(a), unique(b)) with system versioning; +insert ignore into t1 (a,b,c) values (1,2,3); + +--disable_cursor_protocol +--disable_ps2_protocol +select a, b, c into outfile '15330.data' from t1; +--enable_ps2_protocol +--enable_cursor_protocol +load data infile '15330.data' ignore into table t1 (a,b,c); +load data infile '15330.data' replace into table t1 (a,b,c); +--let $datadir=`select @@datadir` +--remove_file $datadir/test/15330.data + +# cleanup +drop table t1; +--disable_query_log +eval set default_storage_engine= $default_engine; +--enable_query_log + --source suite/versioning/common_finish.inc From 55b599320503659fb2c5671bc894f66954c4beea Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 3 Dec 2024 13:49:42 +0300 Subject: [PATCH 12/15] Cleanup: make_keypart_map inline for easier debugging. --- sql/handler.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index fc3d00d43d5..ad1cbaff5b7 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2980,12 +2980,19 @@ uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map); bitmap with first N+1 bits set (keypart_map for a key prefix of [0..N] keyparts) */ -#define make_keypart_map(N) (((key_part_map)2 << (N)) - 1) +inline key_part_map make_keypart_map(uint N) +{ + return ((key_part_map)2 << (N)) - 1; +} + /* bitmap with first N bits set (keypart_map for a key prefix of [0..N-1] keyparts) */ -#define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1) +inline key_part_map make_prev_keypart_map(uint N) +{ + return ((key_part_map)1 << (N)) - 1; +} /** Base class to be used by handlers different shares */ From 27c25ceedbde07649d282fe0859defc7f724473c Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 3 Dec 2024 13:49:42 +0300 Subject: [PATCH 13/15] MDEV-31030 Assertion `!error' failed in ha_partition::update_row on UPDATE Removing wrong assertion as division by zero was caused by valid input. --- mysql-test/main/partition.result | 20 ++++++++++++++++++++ mysql-test/main/partition.test | 16 ++++++++++++++++ sql/ha_partition.cc | 5 ++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/partition.result b/mysql-test/main/partition.result index e18273f4fe9..8cf64927293 100644 --- a/mysql-test/main/partition.result +++ b/mysql-test/main/partition.result @@ -2857,3 +2857,23 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t3 ref_or_null a1,b a1 10 func,test.t2.a 198 Using where; Full scan on NULL key set optimizer_switch=@tmp_os; drop table t1,t2,t3; +# +# MDEV-31030 Assertion `!error' failed in ha_partition::update_row on UPDATE +# +create table t (c int) +partition by list (1 div c) ( +partition p0 values in (null), +partition p values in (1)); +insert ignore into t values (0), (1), (0); +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +update t set c= 2; +ERROR HY000: Table has no partition for value 0 +update ignore t set c= 3; +select * from t; +c +0 +0 +1 +drop table t; diff --git a/mysql-test/main/partition.test b/mysql-test/main/partition.test index b3ea7f5c274..b9e055783ca 100644 --- a/mysql-test/main/partition.test +++ b/mysql-test/main/partition.test @@ -3068,3 +3068,19 @@ set optimizer_switch=@tmp_os; drop table t1,t2,t3; +--echo # +--echo # MDEV-31030 Assertion `!error' failed in ha_partition::update_row on UPDATE +--echo # + +create table t (c int) +partition by list (1 div c) ( + partition p0 values in (null), + partition p values in (1)); +insert ignore into t values (0), (1), (0); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +update t set c= 2; +--disable_warnings +update ignore t set c= 3; +--enable_warnings +select * from t; +drop table t; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index ed7fb7fe5f9..2a06ca4300e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4591,7 +4591,10 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data) Notice that HA_READ_BEFORE_WRITE_REMOVAL does not require this protocol, so this is not supported for this engine. */ - error= get_part_for_buf(old_data, m_rec0, m_part_info, &old_part_id); + { + Abort_on_warning_instant_set old_abort_on_warning(thd, 0); + error= get_part_for_buf(old_data, m_rec0, m_part_info, &old_part_id); + } DBUG_ASSERT(!error); DBUG_ASSERT(old_part_id == m_last_part); DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), old_part_id)); From 13f93da1f60f6f51ebe9a1f3e3fcfd6caa54c07f Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 3 Dec 2024 13:49:43 +0300 Subject: [PATCH 14/15] MDEV-33783 CREATE SERVER segfaults on wrong mysql.servers Do basic checking of mysql.servers compatibility. --- mysql-test/main/servers.result | 14 +++++++ mysql-test/main/servers.test | 15 +++++++ sql/sql_servers.cc | 77 ++++++++++++++++++++++------------ 3 files changed, 80 insertions(+), 26 deletions(-) diff --git a/mysql-test/main/servers.result b/mysql-test/main/servers.result index 585f0f62af0..c466967a0db 100644 --- a/mysql-test/main/servers.result +++ b/mysql-test/main/servers.result @@ -24,3 +24,17 @@ SELECT * FROM mysql.servers; Server_name Host Db Username Password Port Socket Wrapper Owner s1 3306 bar mysql DROP SERVER s1; +# +# MDEV-33783 CREATE SERVER segfaults on wrong mysql.servers +# +create server s1 foreign data wrapper foo options(user 'a'); +alter server s1 options(host 'server.example.org'); +rename table mysql.servers to mysql.servers_save; +create table mysql.servers (x int); +alter server s1 options(host 'server.example.org'); +ERROR HY000: The foreign server name you are trying to reference does not exist. Data source error: s1 +create server s2 foreign data wrapper foo options(user 'a'); +ERROR HY000: Can't read record in system table +drop table mysql.servers; +rename table mysql.servers_save to mysql.servers; +drop server s1; diff --git a/mysql-test/main/servers.test b/mysql-test/main/servers.test index 645206c376e..6aaaa356c1d 100644 --- a/mysql-test/main/servers.test +++ b/mysql-test/main/servers.test @@ -22,3 +22,18 @@ DROP SERVER s1; CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS(SOCKET 'bar'); SELECT * FROM mysql.servers; DROP SERVER s1; + +--echo # +--echo # MDEV-33783 CREATE SERVER segfaults on wrong mysql.servers +--echo # +create server s1 foreign data wrapper foo options(user 'a'); +alter server s1 options(host 'server.example.org'); +rename table mysql.servers to mysql.servers_save; +create table mysql.servers (x int); +--error ER_FOREIGN_SERVER_DOESNT_EXIST +alter server s1 options(host 'server.example.org'); +--error ER_CANT_FIND_SYSTEM_REC +create server s2 foreign data wrapper foo options(user 'a'); +drop table mysql.servers; +rename table mysql.servers_save to mysql.servers; +drop server s1; diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 8350b9dba9b..59a4679847b 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -462,7 +462,7 @@ get_server_from_table_to_cache(TABLE *table) RETURN VALUES 0 - no error - other - error code + other - ER_ error code */ static int @@ -546,15 +546,19 @@ insert_server_record_into_cache(FOREIGN_SERVER *server) advance of insertion into the mysql.servers table RETURN VALUE - VOID - + 0 - no errors + >0 - ER_ error code */ -static void +static int store_server_fields(TABLE *table, FOREIGN_SERVER *server) { table->use_all_columns(); + + if (table->s->fields < 9) + return ER_CANT_FIND_SYSTEM_REC; + /* "server" has already been prepped by prepare_server_struct_for_<> so, all we need to do is check if the value is set (> -1 for port) @@ -563,30 +567,43 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server) have changed will be set. If an insert, then all will be set, even if with empty strings */ - if (server->host) + if (server->host && table->field[1]->store(server->host, - (uint) strlen(server->host), system_charset_info); - if (server->db) + (uint) strlen(server->host), system_charset_info)) + goto err; + if (server->db && table->field[2]->store(server->db, - (uint) strlen(server->db), system_charset_info); - if (server->username) + (uint) strlen(server->db), system_charset_info)) + goto err; + if (server->username && table->field[3]->store(server->username, - (uint) strlen(server->username), system_charset_info); - if (server->password) + (uint) strlen(server->username), system_charset_info)) + goto err; + if (server->password && table->field[4]->store(server->password, - (uint) strlen(server->password), system_charset_info); - if (server->port > -1) - table->field[5]->store(server->port); - - if (server->socket) + (uint) strlen(server->password), system_charset_info)) + goto err; + if (server->port > -1 && + table->field[5]->store(server->port)) + goto err; + if (server->socket && table->field[6]->store(server->socket, - (uint) strlen(server->socket), system_charset_info); - if (server->scheme) + (uint) strlen(server->socket), system_charset_info)) + goto err; + if (server->scheme && table->field[7]->store(server->scheme, - (uint) strlen(server->scheme), system_charset_info); - if (server->owner) + (uint) strlen(server->scheme), system_charset_info)) + goto err; + if (server->owner && table->field[8]->store(server->owner, - (uint) strlen(server->owner), system_charset_info); + (uint) strlen(server->owner), system_charset_info)) + goto err; + return 0; + +err: + THD *thd= table->in_use; + DBUG_ASSERT(thd->is_error()); + return thd->get_stmt_da()->get_sql_errno(); } /* @@ -608,7 +625,7 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server) RETURN VALUE 0 - no errors - >0 - error code + >0 - ER_ error code */ @@ -642,7 +659,8 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server) error= 1; } /* store each field to be inserted */ - store_server_fields(table, server); + if ((error= store_server_fields(table, server))) + DBUG_RETURN(error); DBUG_PRINT("info",("record for server '%s' not found!", server->server_name)); @@ -972,9 +990,15 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server) table->use_all_columns(); /* set the field that's the PK to the value we're looking for */ - table->field[0]->store(server->server_name, + if (table->field[0]->store(server->server_name, server->server_name_length, - system_charset_info); + system_charset_info)) + { + DBUG_ASSERT(0); /* Protected by servers_cache */ + THD *thd= table->in_use; + DBUG_ASSERT(thd->is_error()); + return thd->get_stmt_da()->get_sql_errno(); + } if (unlikely((error= table->file->ha_index_read_idx_map(table->record[0], 0, @@ -992,7 +1016,8 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server) { /* ok, so we can update since the record exists in the table */ store_record(table,record[1]); - store_server_fields(table, server); + if ((error= store_server_fields(table, server))) + goto end; if (unlikely((error=table->file->ha_update_row(table->record[1], table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME)) From b8ad202da1336550e6987a9c673d1a23e4b26e7b Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 3 Dec 2024 13:49:43 +0300 Subject: [PATCH 15/15] MDEV-34770 UBSAN: runtime error: load of address 0x... with insufficient space for an object of type 'uchar' in sys_vars.inl Disable UBSAN for global_var_ptr()/session_var_ptr() (none of "undefined" suboptions for gcc-13 worked). --- sql/set_var.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/set_var.h b/sql/set_var.h index c8da3c1c169..416993e5c34 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -247,9 +247,11 @@ protected: Typically it's the same as session_value_ptr(), but it's different, for example, for ENUM, that is printed as a string, but stored as a number. */ + __attribute__((no_sanitize("undefined"))) uchar *session_var_ptr(THD *thd) const { return ((uchar*)&(thd->variables)) + offset; } + __attribute__((no_sanitize("undefined"))) uchar *global_var_ptr() const { return ((uchar*)&global_system_variables) + offset; }