diff --git a/CMakeLists.txt b/CMakeLists.txt index 74fdbcbc0c5..617226b5a36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,11 +194,7 @@ ELSE() ENDIF() -IF("${MYSQL_NO_DASH_VERSION}" VERSION_LESS 11.2) - SET(MEMPROTECT_DEFAULT ON) -ELSE() - SET(MEMPROTECT_DEFAULT OFF) -ENDIF() +SET(MEMPROTECT_DEFAULT ON) OPTION(WITH_PROTECT_STATEMENT_MEMROOT "Enable protection of statement's memory root after first SP/PS execution. Turned into account only for debug build" ${MEMPROTECT_DEFAULT}) diff --git a/CREDITS b/CREDITS index 35604064980..42f1697f992 100644 --- a/CREDITS +++ b/CREDITS @@ -1,20 +1,48 @@ MariaDB is brought to you by the MariaDB Foundation, a non profit organization registered in the USA. -The current main sponsors of the MariaDB Foundation are: +As of August 2024, the main sponsors of the MariaDB Foundation are: -Alibaba Cloud https://www.alibabacloud.com/ (2017) -Intel https://www.intel.com (2022) -MariaDB Corporation https://www.mariadb.com (2013) -Microsoft https://microsoft.com/ (2017) -ServiceNow https://servicenow.com (2019) -SIT https://sit.org (2022) -Tencent Cloud https://cloud.tencent.com (2017) -Development Bank of Singapore https://dbs.com (2016) -IBM https://www.ibm.com (2017) -Automattic https://automattic.com (2019) -Galera Cluster https://galeracluster.com (2020) -Percona https://www.percona.com (2018) +Amazon https://amazon.com +Acronis https://www.acronis.com +Alibaba Cloud https://www.alibabacloud.com +C>onstructor https://constructor.org +Development Bank of Singapore https://www.dbs.com +Intel https://www.intel.com +MariaDB plc https://www.mariadb.com +ServiceNow https://servicenow.com +WebPros https://webpros.com +IBM https://www.ibm.com +IONOS https://www.ionos.com +Automattic https://automattic.com +SkySQL https://skysql.com +team.blue https://team.blue +Tencent Cloud https://cloud.tencent.com +Wikimedia Foundation https://www.wikimediafoundation.org +Cyber Leo https://cyberleo.com +Hetzner https://www.hetzner.com +Rumahweb https://www.rumahweb.com +Tasjeel.ae https://www.tasjeel.ae +Galera Cluster https://galeracluster.com +Percona https://www.percona.com +Vettabase https://vettabase.com + +Previous sponsors include: + +Booking.com +Jelastic.com +Microsoft +Nexedi +Open Query +Planeetta Web Hosting +SpringbokSQL +Tencent Games +Tencent Game DBA +Tencent TDSQL +Verkkokauppa +Virtuozzo +Visma +Webyog For a full list of sponsors, see https://mariadb.org/about/#sponsors @@ -27,7 +55,7 @@ For all corporate sponsorships please contact the MariaDB Foundation Board via foundation@mariadb.org. The MariaDB Foundation is responsible for the MariaDB source -repository, the official MariaDB binaries and http://mariadb.org. +repository, the official MariaDB binaries and https://mariadb.org. The MariaDB Foundation also provides, among other things, the following services to the MariaDB community: @@ -37,8 +65,8 @@ following services to the MariaDB community: - Merging MySQL patches into MariaDB - Bug fixing in MariaDB (for bugs that affects a large part of the community) - Building the official MariaDB binaries -- Maintaining http://mariadb.org -- Documenting MariaDB in the MariaDB Knowledge Base http://mariadb.com/kb +- Maintaining https://mariadb.org +- Documenting MariaDB in the MariaDB Knowledge Base https://mariadb.com/kb To be able to do the above we need help from corporations and individuals! @@ -49,8 +77,5 @@ go to https://mariadb.org/donate/ You can get a list of all the main authors of MariaDB / MySQL by running SHOW AUTHORS; -You can get a list sponsors and contributors by running -SHOW CONTRIBUTORS; - You can read more about the MariaDB Foundation at: https://mariadb.org/about/ diff --git a/client/mysqlimport.cc b/client/mysqlimport.cc index 4a0cfe95c9c..b8c92b76950 100644 --- a/client/mysqlimport.cc +++ b/client/mysqlimport.cc @@ -290,7 +290,6 @@ get_one_option(const struct my_option *opt, const char *argument, #ifdef _WIN32 case 'W': opt_protocol = MYSQL_PROTOCOL_PIPE; - opt_local_file=1; break; #endif case OPT_MYSQL_PROTOCOL: diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 19915b60a85..a8c019e8ebe 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -247,9 +247,9 @@ SETA(CPACK_RPM_server_PACKAGE_REQUIRES IF(WITH_WSREP) SETA(CPACK_RPM_server_PACKAGE_REQUIRES - "galera-4" "rsync" "lsof" "grep" "gawk" "iproute" + "galera-4" "rsync" "grep" "gawk" "iproute" "coreutils" "findutils" "tar") - SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "pv") + SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "lsof" "pv") ENDIF() SET(CPACK_RPM_server_PRE_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-prein.sh) diff --git a/cmake/mariadb_connector_c.cmake b/cmake/mariadb_connector_c.cmake index 542c6e65365..ff236d7500e 100644 --- a/cmake/mariadb_connector_c.cmake +++ b/cmake/mariadb_connector_c.cmake @@ -13,15 +13,17 @@ IF(HAVE_THREADS_H) SET(CLIENT_PLUGIN_PARSEC DYNAMIC) ENDIF() -IF(SSL_DEFINES MATCHES "WOLFSSL") - IF(WIN32) - SET(CONC_WITH_SSL "SCHANNEL") +IF(NOT CONC_WITH_SSL) + IF(SSL_DEFINES MATCHES "WOLFSSL") + IF(WIN32) + SET(CONC_WITH_SSL "SCHANNEL") + ELSE() + SET(CONC_WITH_SSL "GNUTLS") # that's what debian wants, right? + ENDIF() ELSE() - SET(CONC_WITH_SSL "GNUTLS") # that's what debian wants, right? + SET(CONC_WITH_SSL "OPENSSL") + SET(OPENSSL_FOUND TRUE) ENDIF() -ELSE() - SET(CONC_WITH_SSL "OPENSSL") - SET(OPENSSL_FOUND TRUE) ENDIF() SET(CONC_WITH_CURL OFF) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 4bea8627f63..aff4b841348 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -2014,7 +2014,7 @@ struct my_option xb_server_options[] = 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, {"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user " - "privileges fro the backup user", + "privileges for the backup user", &opt_check_privileges, &opt_check_privileges, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, diff --git a/extra/perror.c b/extra/perror.c index b0115e14c04..8f4c92fbfd0 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -199,7 +199,8 @@ static my_bool print_win_error_msg(DWORD error, my_bool verbose) char *s; if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, (char *)&s, 0, + NULL, error, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (char *) &s, 0, NULL)) { char* end = s + strlen(s) - 1; diff --git a/include/m_string.h b/include/m_string.h index d3b7499378d..a8b4e4d4c49 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -265,9 +265,20 @@ static inline void safe_strcpy(char *dst, size_t dst_size, const char *src) * * 2) IF there is no 0 byte in the first dst_size bytes of src, strncpy will * copy dst_size bytes, and the final byte won't be 0. + * + * In GCC 8+, the `-Wstringop-truncation` warning may object to strncpy() + * being used in this way, so we need to disable this warning for this + * single statement. */ +#if defined __GNUC__ && __GNUC__ >= 8 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" +#endif strncpy(dst, src, dst_size); +#if defined __GNUC__ && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif dst[dst_size - 1]= 0; } diff --git a/mysql-test/include/not_valgrind_build.inc b/mysql-test/include/not_valgrind_build.inc new file mode 100644 index 00000000000..b62a1bc953b --- /dev/null +++ b/mysql-test/include/not_valgrind_build.inc @@ -0,0 +1,4 @@ +if (`select version() like '%valgrind%' || version() like '%asan%'`) +{ + skip Does not run with binaries built with valgrind or asan; +} diff --git a/mysql-test/main/contributors.result b/mysql-test/main/contributors.result index 8d72373696c..9126385faa0 100644 --- a/mysql-test/main/contributors.result +++ b/mysql-test/main/contributors.result @@ -1,18 +1,42 @@ SHOW CONTRIBUTORS; Name Location Comment +Amazon https://www.amazon.com/ Diamond Sponsor of the MariaDB Foundation +Acronis https://www.acronis.com/ Platinum Sponsor of the MariaDB Foundation Alibaba Cloud https://www.alibabacloud.com/ Platinum Sponsor of the MariaDB Foundation -Tencent Cloud https://cloud.tencent.com Platinum Sponsor of the MariaDB Foundation -Microsoft https://microsoft.com/ Platinum Sponsor of the MariaDB Foundation -MariaDB Corporation https://mariadb.com Founding member, Platinum Sponsor of the MariaDB Foundation -ServiceNow https://servicenow.com Platinum Sponsor of the MariaDB Foundation -Intel https://www.intel.com Platinum Sponsor of the MariaDB Foundation -SIT https://sit.org Platinum Sponsor of the MariaDB Foundation -Visma https://visma.com Gold Sponsor of the MariaDB Foundation -DBS https://dbs.com Gold Sponsor of the MariaDB Foundation -IBM https://www.ibm.com Gold Sponsor of the MariaDB Foundation -Automattic https://automattic.com Silver Sponsor of the MariaDB Foundation +C5; c c DROP TABLE t1, t2; SET optimizer_switch=default; +# +# MDEV-34683 Types mismatch when cloning items causes debug assertion +# +CREATE TABLE t1 (a date); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +SELECT a FROM v1 WHERE a IN ('a', 'b', 'c'); +a +CREATE VIEW v2 AS SELECT '' as a; +SELECT * FROM v2 WHERE a='' AND CASE '' WHEN '' THEN '' ELSE a END=''; +a + +DROP TABLE t1; +DROP VIEW v1, v2; +# +# MDEV-34771: Types mismatch when cloning items causes debug assertion +# +CREATE VIEW t AS SELECT 1 AS a; +SELECT * FROM t WHERE a=b''; +a +drop view t; +# +# MDEV-34776: Assertion failure in Item_string::do_build_clone +# +CREATE VIEW v AS SELECT version() AS f; +SELECT * FROM v WHERE f = '10.5.20'; +f +drop view v; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/item_types.test b/mysql-test/main/item_types.test index f43bfe1a8ac..2818ae582af 100644 --- a/mysql-test/main/item_types.test +++ b/mysql-test/main/item_types.test @@ -13,3 +13,39 @@ SELECT * FROM t1 JOIN t2 ON t1.c=t2.c WHERE t1.c<=>5; DROP TABLE t1, t2; SET optimizer_switch=default; + +--echo # +--echo # MDEV-34683 Types mismatch when cloning items causes debug assertion +--echo # + +CREATE TABLE t1 (a date); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +--disable_warnings +SELECT a FROM v1 WHERE a IN ('a', 'b', 'c'); +--enable_warnings + +CREATE VIEW v2 AS SELECT '' as a; +SELECT * FROM v2 WHERE a='' AND CASE '' WHEN '' THEN '' ELSE a END=''; + +DROP TABLE t1; +DROP VIEW v1, v2; + +--echo # +--echo # MDEV-34771: Types mismatch when cloning items causes debug assertion +--echo # + +CREATE VIEW t AS SELECT 1 AS a; +SELECT * FROM t WHERE a=b''; +drop view t; + +--echo # +--echo # MDEV-34776: Assertion failure in Item_string::do_build_clone +--echo # + +CREATE VIEW v AS SELECT version() AS f; +SELECT * FROM v WHERE f = '10.5.20'; +drop view v; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result index e934c24288c..95a1f317ae0 100644 --- a/mysql-test/main/ps_mem_leaks.result +++ b/mysql-test/main/ps_mem_leaks.result @@ -149,6 +149,20 @@ DROP TABLE t1; DROP PROCEDURE p1; # End of 10.11 tests # +# MDEV-34649: Memory leaks on running DELETE statement in PS mode with positional parameters +# +CREATE TABLE t1 (a INT, b VARCHAR(30)) CHARSET=utf8mb4; +INSERT INTO t1 VALUES (1, 'one'), (0, NULL), (3, 'three'), (4, 'four'); +PREPARE stmt FROM 'DELETE FROM t1 WHERE b=?' ; +SET @arg00=NULL; +EXECUTE stmt USING @arg00; +SET @arg00='one'; +EXECUTE stmt USING @arg00; +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +# End of 11.1 +# # MDEV-34517: Memory leak on re-compilation of a failing statement inside a stored routine # CREATE TABLE t1 (a INT); diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test index 17baf122d16..951bc7e337a 100644 --- a/mysql-test/main/ps_mem_leaks.test +++ b/mysql-test/main/ps_mem_leaks.test @@ -168,6 +168,24 @@ DROP PROCEDURE p1; --echo # End of 10.11 tests +--echo # +--echo # MDEV-34649: Memory leaks on running DELETE statement in PS mode with positional parameters +--echo # +CREATE TABLE t1 (a INT, b VARCHAR(30)) CHARSET=utf8mb4; +INSERT INTO t1 VALUES (1, 'one'), (0, NULL), (3, 'three'), (4, 'four'); +PREPARE stmt FROM 'DELETE FROM t1 WHERE b=?' ; +SET @arg00=NULL; +EXECUTE stmt USING @arg00; +SET @arg00='one'; +# Without the patch, attempt to run the same prepared statement the second time +# would result in memory leaks +EXECUTE stmt USING @arg00; +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo # End of 11.1 + --echo # --echo # MDEV-34517: Memory leak on re-compilation of a failing statement inside a stored routine --echo # diff --git a/mysql-test/main/sp-no-valgrind.test b/mysql-test/main/sp-no-valgrind.test index 1b4a0f84f1e..6bacc7b150c 100644 --- a/mysql-test/main/sp-no-valgrind.test +++ b/mysql-test/main/sp-no-valgrind.test @@ -1,5 +1,5 @@ --source include/not_msan.inc ---source include/not_valgrind.inc +--source include/not_valgrind_build.inc --echo # MDEV-20699 do not cache SP in SHOW CREATE --echo # Warmup round, this might allocate some memory for session variable diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 85d602877d6..97c563b5bbe 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -5956,6 +5956,7 @@ WHERE SLEEP(0.1) OR c < 'p' OR b = ( SELECT MIN(b) FROM t2 ); --echo # The following shows that t2 was indeed scanned with a full scan. --sorted_result select TABLE_SCHEMA, TABLE_NAME, ROWS_READ, ROWS_CHANGED, ROWS_CHANGED_X_INDEXES, ROWS_INSERTED, ROWS_UPDATED, ROWS_DELETED, KEY_READ_HITS, KEY_READ_MISSES from information_schema.table_statistics; +--sorted_result show index_statistics; set global userstat=@tmp_mdev410; diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result index 94937fcd73c..657aaffa093 100644 --- a/mysql-test/main/union.result +++ b/mysql-test/main/union.result @@ -849,7 +849,7 @@ teeeeeeeeeeeest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `b` mediumblob DEFAULT NULL + `b` blob DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci drop table t1,t2; create table t1 select 1 union select -1; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 7c62f6394d1..4f0619ca540 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -20,5 +20,3 @@ galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATIN 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() galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() -galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed -galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes diff --git a/mysql-test/suite/galera/r/MDEV-34594.result b/mysql-test/suite/galera/r/MDEV-34594.result new file mode 100644 index 00000000000..f9caeba8e59 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-34594.result @@ -0,0 +1,88 @@ +connection node_2; +connection node_1; +# +# Case 1: test with binlog_format ROW +# +connection node_1; +SET @@binlog_format=ROW; +CREATE TABLE t1 (a INT UNIQUE) SELECT 1 AS a,2 AS b UNION SELECT 2 AS a,3 AS c; +CREATE TABLE t2 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a,3 AS c; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 3 +connection node_2; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 3 +DROP TABLE t1,t2; +# +# Case 2: test with binlog_format MIXED +# +connection node_1; +SET @@binlog_format=MIXED; +Warnings: +Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED +CREATE TABLE t1 (a INT UNIQUE) SELECT 1 AS a,2 AS b UNION SELECT 2 AS a,3 AS c; +Warnings: +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +CREATE TABLE t2 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a,3 AS c; +Warnings: +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 3 +connection node_2; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 3 +DROP TABLE t1,t2; +# +# Case 3: test with binlog_format STATEMENT +# +connection node_1; +SET @@binlog_format=STATEMENT; +Warnings: +Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT +CREATE TABLE t1 (a INT UNIQUE) SELECT 1 AS a,2 AS b UNION SELECT 2 AS a,3 AS c; +Warnings: +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +CREATE TABLE t2 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a,3 AS c; +Warnings: +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 3 +connection node_2; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 3 +DROP TABLE t1,t2; +connection node_1; diff --git a/mysql-test/suite/galera/r/MDEV-34647.result b/mysql-test/suite/galera/r/MDEV-34647.result new file mode 100644 index 00000000000..16a4e839f13 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-34647.result @@ -0,0 +1,100 @@ +connection node_2; +connection node_1; +create table t1(id serial, val varchar(100)) engine=myisam; +insert into t1 values(null, 'a'); +insert into t1 values(null, 'b'); +insert into t1 select null, 'c'; +insert into t1 select null, 'd' from t1; +select * from t1; +id val +1 a +3 b +5 c +7 d +9 d +11 d +create table t2(id serial, val varchar(100)) engine=aria; +insert into t2 values(null, 'a'); +insert into t2 values(null, 'b'); +insert into t2 select null, 'c'; +insert into t2 select null, 'd' from t2; +select * from t2; +id val +1 a +3 b +5 c +7 d +9 d +11 d +create table t3(id serial, val varchar(100)) engine=innodb; +insert into t3 values(null, 'a'); +insert into t3 values(null, 'b'); +insert into t3 select null, 'c'; +insert into t3 select null, 'd' from t3; +select * from t3; +id val +1 a +3 b +5 c +7 d +9 d +11 d +set global wsrep_mode=REPLICATE_MYISAM; +create table t4(id serial, val varchar(100)) engine=myisam; +insert into t4 values(null, 'a'); +insert into t4 values(null, 'b'); +insert into t4 select null, 'c'; +insert into t4 select null, 'd' from t4; +select * from t4; +id val +1 a +2 b +3 c +4 d +5 d +6 d +create table t5(id serial, val varchar(100)) engine=myisam; +insert into t5 values(null, 'a'); +insert into t5 values(null, 'b'); +insert into t5 select null, 'c'; +insert into t5 select null, 'd' from t5; +select * from t2; +id val +1 a +3 b +5 c +7 d +9 d +11 d +connection node_2; +select * from t1; +id val +select * from t2; +id val +select * from t3; +id val +1 a +3 b +5 c +7 d +9 d +11 d +select * from t4; +id val +1 a +2 b +3 c +4 d +5 d +6 d +select * from t5; +id val +1 a +2 b +3 c +4 d +5 d +6 d +connection node_1; +drop table t1,t2,t3,t4,t5; +set global wsrep_mode=default; diff --git a/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result index 0b32f43704f..215f2b132b8 100644 --- a/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result +++ b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result @@ -7,27 +7,61 @@ SET GLOBAL wsrep_on = OFF; CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = ON; DROP TABLE t1; +connection node_2; +SHOW TABLES; +Tables_in_test +connection node_1; SET GLOBAL wsrep_on = OFF; CREATE SCHEMA s1; SET GLOBAL wsrep_on = ON; DROP SCHEMA s1; +connection node_2; +SHOW SCHEMAS; +Database +information_schema +mtr +mysql +performance_schema +sys +test +connection node_1; CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; CREATE INDEX idx1 ON t1 (f1); SET GLOBAL wsrep_on = ON; DROP INDEX idx1 ON t1; +connection node_2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci DROP TABLE t1; +connection node_1; CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; CREATE INDEX idx1 ON t1 (f1); SET GLOBAL wsrep_on = ON; ALTER TABLE t1 DROP INDEX idx1; +connection node_2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci DROP TABLE t1; +connection node_1; CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; ALTER TABLE t1 ADD COLUMN f2 INTEGER; SET GLOBAL wsrep_on = ON; ALTER TABLE t1 DROP COLUMN f2; +connection node_2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci DROP TABLE t1; connection node_2; SET GLOBAL wsrep_ignore_apply_errors = 2; @@ -37,12 +71,11 @@ SET GLOBAL wsrep_on = OFF; INSERT INTO t1 VALUES (1); SET GLOBAL wsrep_on = ON; DELETE FROM t1 WHERE f1 = 1; -connection node_1; -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) AS expect_0 FROM t1; expect_0 0 connection node_2; -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) AS expect_0 FROM t1; expect_0 0 DROP TABLE t1; @@ -57,12 +90,11 @@ INSERT INTO t1 VALUES (3); DELETE FROM t1 WHERE f1 = 1; DELETE FROM t1 WHERE f1 = 2; COMMIT; -connection node_1; -SELECT COUNT(*) as expect_1 FROM t1; +SELECT COUNT(*) AS expect_1 FROM t1; expect_1 1 connection node_2; -SELECT COUNT(*) as expect_1 FROM t1; +SELECT COUNT(*) AS expect_1 FROM t1; expect_1 1 DROP TABLE t1; @@ -75,14 +107,14 @@ DELETE FROM t1 WHERE f1 = 3; SET SESSION wsrep_on = ON; connection node_1; DELETE FROM t1; -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) AS expect_0 FROM t1; expect_0 0 connection node_2; -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; -VARIABLE_VALUE = 'Primary' -1 -SELECT COUNT(*) as expect_0 FROM t1; +SELECT VARIABLE_VALUE expect_Primary FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +expect_Primary +Primary +SELECT COUNT(*) AS expect_0 FROM t1; expect_0 0 DROP TABLE t1; @@ -103,14 +135,14 @@ DELETE FROM t1 WHERE f1 = 4; DELETE FROM t1 WHERE f1 = 5; COMMIT; SET AUTOCOMMIT=ON; -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) AS expect_0 FROM t1; expect_0 0 connection node_2; -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; -VARIABLE_VALUE = 'Primary' -1 -SELECT COUNT(*) as expect_0 FROM t1; +SELECT VARIABLE_VALUE expect_Primary FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +expect_Primary +Primary +SELECT COUNT(*) AS expect_0 FROM t1; expect_0 0 DROP TABLE t1; @@ -126,14 +158,14 @@ DELETE FROM t1 WHERE f1 = 3; SET SESSION wsrep_on = ON; connection node_1; DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1; -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) expect_0 FROM t1; expect_0 0 connection node_2; -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'Primary' FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) expect_0 FROM t1; expect_0 0 DROP TABLE t1,t2; @@ -148,20 +180,20 @@ DELETE FROM child WHERE parent_id = 2; SET SESSION wsrep_on = ON; connection node_1; DELETE FROM parent; -SELECT COUNT(*) as expect_0 FROM parent; +SELECT COUNT(*) AS expect_0 FROM parent; expect_0 0 -SELECT COUNT(*) as expect_0 FROM child; +SELECT COUNT(*) AS expect_0 FROM child; expect_0 0 connection node_2; -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'Primary' FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 -SELECT COUNT(*) as expect_0 FROM parent; +SELECT COUNT(*) AS expect_0 FROM parent; expect_0 0 -SELECT COUNT(*) as expect_0 FROM child; +SELECT COUNT(*) AS expect_0 FROM child; expect_0 0 DROP TABLE child, parent; @@ -175,8 +207,10 @@ connection node_1; CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); DROP TABLE t1; connection node_2; +SELECT * FROM t1; +ERROR 42S02: Table 'test.t1' doesn't exist SET GLOBAL wsrep_ignore_apply_errors = 7; -CALL mtr.add_suppression("Can't find record in 't.*'"); +CALL mtr.add_suppression("Can't find record in "); CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event"); CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test\\.t1'' on query\\. Default database: 'test'\\. Query: 'DROP TABLE t1', Error_code: 1051"); CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query\\. Default database: 'test'\\. Query: 'DROP SCHEMA s1', Error_code: 1008"); diff --git a/mysql-test/suite/galera/r/mdev-22063.result b/mysql-test/suite/galera/r/mdev-22063.result index 155d1ebbe4f..585d70acb61 100644 --- a/mysql-test/suite/galera/r/mdev-22063.result +++ b/mysql-test/suite/galera/r/mdev-22063.result @@ -64,6 +64,7 @@ id a connection node_1; DROP TABLE t,t2,t3; # Bigger REPLACE ... AS SELECT test +SET GLOBAL wsrep_mode=REPLICATE_MYISAM; CREATE TABLE t1(id int not null primary key ,b int) ENGINE=InnoDB; CREATE TABLE t2(id int not null primary key ,b int) ENGINE=MyISAM; CREATE TABLE t3(id int not null primary key ,b int) ENGINE=Aria; @@ -113,7 +114,7 @@ EXPECT_1000 1000 SELECT COUNT(*) AS EXPECT_1000 FROM t3; EXPECT_1000 -1000 +0 SELECT COUNT(*) AS EXPECT_1000 FROM t4; EXPECT_1000 1000 @@ -126,9 +127,9 @@ EXPECT_1000 SELECT COUNT(*) AS EXPECT_1000 FROM t7; EXPECT_1000 1000 -SELECT COUNT(*) AS EXPECT_1000 FROM t8; -EXPECT_1000 -1000 +SELECT COUNT(*) AS EXPECT_0 FROM t8; +EXPECT_0 +0 connection node_1; DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; # Bigger INSERT INTO ... SELECT test @@ -181,7 +182,7 @@ EXPECT_1000 1000 SELECT COUNT(*) AS EXPECT_1000 FROM t3; EXPECT_1000 -1000 +0 SELECT COUNT(*) AS EXPECT_1000 FROM t4; EXPECT_1000 1000 @@ -194,9 +195,9 @@ EXPECT_1000 SELECT COUNT(*) AS EXPECT_1000 FROM t7; EXPECT_1000 1000 -SELECT COUNT(*) AS EXPECT_1000 FROM t8; -EXPECT_1000 -1000 +SELECT COUNT(*) AS EXPECT_0 FROM t8; +EXPECT_0 +0 connection node_1; DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; CREATE TABLE t1(pk int not null primary key) engine=innodb; diff --git a/mysql-test/suite/galera/t/MDEV-34594.test b/mysql-test/suite/galera/t/MDEV-34594.test new file mode 100644 index 00000000000..256070cf40d --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-34594.test @@ -0,0 +1,68 @@ +--source include/galera_cluster.inc +--source include/log_bin.inc + +--echo # +--echo # Case 1: test with binlog_format ROW +--echo # +--connection node_1 +SET @@binlog_format=ROW; +CREATE TABLE t1 (a INT UNIQUE) SELECT 1 AS a,2 AS b UNION SELECT 2 AS a,3 AS c; +# +# Note that this has two rows (1,2) and (1,3) where (1,3) contains duplicate key +# but we requested REPLACE --> ::update_row() is called to update (1,2) --> (1,3) +# +CREATE TABLE t2 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a,3 AS c; +SELECT * FROM t1; +SELECT * FROM t2; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc + +SELECT * FROM t1; +SELECT * FROM t2; +DROP TABLE t1,t2; + +--echo # +--echo # Case 2: test with binlog_format MIXED +--echo # +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc +SET @@binlog_format=MIXED; +CREATE TABLE t1 (a INT UNIQUE) SELECT 1 AS a,2 AS b UNION SELECT 2 AS a,3 AS c; +CREATE TABLE t2 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a,3 AS c; +SELECT * FROM t1; +SELECT * FROM t2; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc + +SELECT * FROM t1; +SELECT * FROM t2; +DROP TABLE t1,t2; + +--echo # +--echo # Case 3: test with binlog_format STATEMENT +--echo # +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc +SET @@binlog_format=STATEMENT; +CREATE TABLE t1 (a INT UNIQUE) SELECT 1 AS a,2 AS b UNION SELECT 2 AS a,3 AS c; +CREATE TABLE t2 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a,3 AS c; +SELECT * FROM t1; +SELECT * FROM t2; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' OR TABLE_NAME = 't1' +--source include/wait_condition.inc + +SELECT * FROM t1; +SELECT * FROM t2; +DROP TABLE t1,t2; + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc diff --git a/mysql-test/suite/galera/t/MDEV-34647.test b/mysql-test/suite/galera/t/MDEV-34647.test new file mode 100644 index 00000000000..8840c233c6d --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-34647.test @@ -0,0 +1,53 @@ +--source include/galera_cluster.inc +--source include/have_aria.inc + +create table t1(id serial, val varchar(100)) engine=myisam; +insert into t1 values(null, 'a'); +insert into t1 values(null, 'b'); +insert into t1 select null, 'c'; +insert into t1 select null, 'd' from t1; +select * from t1; + +create table t2(id serial, val varchar(100)) engine=aria; +insert into t2 values(null, 'a'); +insert into t2 values(null, 'b'); +insert into t2 select null, 'c'; +insert into t2 select null, 'd' from t2; +select * from t2; + +create table t3(id serial, val varchar(100)) engine=innodb; +insert into t3 values(null, 'a'); +insert into t3 values(null, 'b'); +insert into t3 select null, 'c'; +insert into t3 select null, 'd' from t3; +select * from t3; + +set global wsrep_mode=REPLICATE_MYISAM; + +create table t4(id serial, val varchar(100)) engine=myisam; +insert into t4 values(null, 'a'); +insert into t4 values(null, 'b'); +insert into t4 select null, 'c'; +insert into t4 select null, 'd' from t4; +select * from t4; + +create table t5(id serial, val varchar(100)) engine=myisam; +insert into t5 values(null, 'a'); +insert into t5 values(null, 'b'); +insert into t5 select null, 'c'; +insert into t5 select null, 'd' from t5; +select * from t2; + + +--connection node_2 +select * from t1; +select * from t2; +select * from t3; +select * from t4; +select * from t5; + + +--connection node_1 +drop table t1,t2,t3,t4,t5; +set global wsrep_mode=default; + diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf index 52ec6af7e74..da04a605291 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf @@ -3,6 +3,11 @@ # We do not set mysqldump-related SST options here because doing so on startup # causes the first MTR connection to be forefully dropped by Galera, which in turn confuses MTR +[mysqld] +wsrep-debug=1 +wsrep-sync_wait=15 +loose-galera_sst_mysqldump_with_key=1 + [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test index 3e0e944b0df..31a88777150 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test @@ -6,6 +6,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_ssl_communication.inc +--source include/force_restart.inc --source suite/galera/include/galera_sst_set_mysqldump.inc --let $node_1=node_1 diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf index 545cc8147e0..1d02401decc 100644 --- a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf +++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf @@ -1,7 +1,6 @@ !include ../galera_2nodes.cnf -[mysqld.1] -wsrep_debug=1 - -[mysqld.2] +[mysqld] wsrep_debug=1 +wsrep_sync_wait=15 +loose-galera-var-ignore-apply-errors=1 diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test index e5bff5d8dc4..de17c95b33e 100644 --- a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test +++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test @@ -2,8 +2,9 @@ # Test option wsrep_ignore_apply_errors # +--source include/have_perfschema.inc --source include/galera_cluster.inc - +--source include/force_restart.inc # # Ignore reconciling DDL errors on node_2 @@ -17,41 +18,55 @@ SET GLOBAL wsrep_ignore_apply_errors = 1; SET GLOBAL wsrep_on = OFF; CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc DROP TABLE t1; +--connection node_2 +SHOW TABLES; + # Drop schema that does not exist +--connection node_1 SET GLOBAL wsrep_on = OFF; CREATE SCHEMA s1; SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc DROP SCHEMA s1; +--connection node_2 +SHOW SCHEMAS; + # Drop index that does not exist using DROP INDEX +--connection node_1 CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; CREATE INDEX idx1 ON t1 (f1); SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc DROP INDEX idx1 ON t1; + +--connection node_2 +SHOW CREATE TABLE t1; DROP TABLE t1; # Drop index that does not exist using ALTER TABLE +--connection node_1 CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; CREATE INDEX idx1 ON t1 (f1); SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc ALTER TABLE t1 DROP INDEX idx1; + +--connection node_2 +SHOW CREATE TABLE t1; DROP TABLE t1; # Drop column that does not exist +--connection node_1 CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; ALTER TABLE t1 ADD COLUMN f2 INTEGER; SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc ALTER TABLE t1 DROP COLUMN f2; + +--connection node_2 +SHOW CREATE TABLE t1; DROP TABLE t1; @@ -68,21 +83,11 @@ CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = OFF; INSERT INTO t1 VALUES (1); SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc DELETE FROM t1 WHERE f1 = 1; +SELECT COUNT(*) AS expect_0 FROM t1; ---connection node_1 ---let $wait_condition = SELECT COUNT(*) = 0 FROM t1; ---source include/wait_condition.inc -SELECT COUNT(*) as expect_0 FROM t1; --connection node_2 ---source include/galera_wait_ready.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 0 FROM t1; ---source include/wait_condition.inc -SELECT COUNT(*) as expect_0 FROM t1; - +SELECT COUNT(*) AS expect_0 FROM t1; DROP TABLE t1; # Delete row that does not exist in a multi statement transaction @@ -92,25 +97,15 @@ INSERT INTO t1 VALUES (2); SET GLOBAL wsrep_on = OFF; INSERT INTO t1 VALUES (1); SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc START TRANSACTION; INSERT INTO t1 VALUES (3); DELETE FROM t1 WHERE f1 = 1; DELETE FROM t1 WHERE f1 = 2; COMMIT; +SELECT COUNT(*) AS expect_1 FROM t1; ---connection node_1 ---let $wait_condition = SELECT COUNT(*) = 1 FROM t1; ---source include/wait_condition.inc -SELECT COUNT(*) as expect_1 FROM t1; --connection node_2 ---source include/galera_wait_ready.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 1 FROM t1; ---source include/wait_condition.inc -SELECT COUNT(*) as expect_1 FROM t1; - +SELECT COUNT(*) AS expect_1 FROM t1; DROP TABLE t1; # @@ -127,21 +122,16 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5); SET SESSION wsrep_on = OFF; DELETE FROM t1 WHERE f1 = 3; SET SESSION wsrep_on = ON; ---source include/galera_wait_ready.inc + --connection node_1 DELETE FROM t1; +SELECT COUNT(*) AS expect_0 FROM t1; -SELECT COUNT(*) as expect_0 FROM t1; --connection node_2 ---source include/galera_wait_ready.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; ---source include/wait_condition.inc -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --let $wait_condition = SELECT COUNT(*) = 0 FROM t1; --source include/wait_condition.inc -SELECT COUNT(*) as expect_0 FROM t1; +SELECT VARIABLE_VALUE expect_Primary FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) AS expect_0 FROM t1; DROP TABLE t1; # @@ -158,10 +148,8 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5); SET SESSION wsrep_on = OFF; DELETE FROM t1 WHERE f1 = 3; SET SESSION wsrep_on = ON; ---source include/galera_wait_ready.inc --connection node_1 - SET AUTOCOMMIT=OFF; START TRANSACTION; DELETE FROM t1 WHERE f1 = 1; @@ -171,18 +159,13 @@ DELETE FROM t1 WHERE f1 = 4; DELETE FROM t1 WHERE f1 = 5; COMMIT; SET AUTOCOMMIT=ON; +SELECT COUNT(*) AS expect_0 FROM t1; -SELECT COUNT(*) as expect_0 FROM t1; --connection node_2 ---source include/galera_wait_ready.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; ---source include/wait_condition.inc -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --let $wait_condition = SELECT COUNT(*) = 0 FROM t1; --source include/wait_condition.inc -SELECT COUNT(*) as expect_0 FROM t1; +SELECT VARIABLE_VALUE expect_Primary FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) AS expect_0 FROM t1; DROP TABLE t1; # @@ -203,22 +186,16 @@ SET SESSION wsrep_on = OFF; DELETE FROM t2 WHERE f1 = 2; DELETE FROM t1 WHERE f1 = 3; SET SESSION wsrep_on = ON; ---source include/galera_wait_ready.inc --connection node_1 DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1; -SELECT COUNT(*) as expect_0 FROM t1; +SELECT COUNT(*) expect_0 FROM t1; --connection node_2 ---source include/galera_wait_ready.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; ---source include/wait_condition.inc -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --let $wait_condition = SELECT COUNT(*) = 0 FROM t1; --source include/wait_condition.inc -SELECT COUNT(*) as expect_0 FROM t1; +SELECT VARIABLE_VALUE = 'Primary' FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) expect_0 FROM t1; DROP TABLE t1,t2; # @@ -238,26 +215,18 @@ INSERT INTO child VALUES (1,1),(2,2),(3,3); SET SESSION wsrep_on = OFF; DELETE FROM child WHERE parent_id = 2; SET SESSION wsrep_on = ON; ---source include/galera_wait_ready.inc --connection node_1 DELETE FROM parent; -SELECT COUNT(*) as expect_0 FROM parent; -SELECT COUNT(*) as expect_0 FROM child; +SELECT COUNT(*) AS expect_0 FROM parent; +SELECT COUNT(*) AS expect_0 FROM child; --connection node_2 ---source include/galera_wait_ready.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; ---source include/wait_condition.inc -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; ---let $wait_condition = SELECT COUNT(*) = 0 FROM parent; ---source include/wait_condition.inc --let $wait_condition = SELECT COUNT(*) = 0 FROM child; --source include/wait_condition.inc -SELECT COUNT(*) as expect_0 FROM parent; -SELECT COUNT(*) as expect_0 FROM child; +SELECT VARIABLE_VALUE = 'Primary' FROM performance_schema.global_status WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) AS expect_0 FROM parent; +SELECT COUNT(*) AS expect_0 FROM child; DROP TABLE child, parent; # @@ -272,15 +241,17 @@ SET GLOBAL wsrep_ignore_apply_errors = 4; SET GLOBAL wsrep_on = OFF; CREATE TABLE t1 (f1 INTEGER); SET GLOBAL wsrep_on = ON; ---source include/galera_wait_ready.inc + --connection node_1 CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); DROP TABLE t1; --connection node_2 +--error ER_NO_SUCH_TABLE +SELECT * FROM t1; SET GLOBAL wsrep_ignore_apply_errors = 7; -CALL mtr.add_suppression("Can't find record in 't.*'"); +CALL mtr.add_suppression("Can't find record in "); CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event"); CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test\\.t1'' on query\\. Default database: 'test'\\. Query: 'DROP TABLE t1', Error_code: 1051"); CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query\\. Default database: 'test'\\. Query: 'DROP SCHEMA s1', Error_code: 1008"); diff --git a/mysql-test/suite/galera/t/mdev-22063.test b/mysql-test/suite/galera/t/mdev-22063.test index d3ddb164d3d..ccc199e308f 100644 --- a/mysql-test/suite/galera/t/mdev-22063.test +++ b/mysql-test/suite/galera/t/mdev-22063.test @@ -64,6 +64,7 @@ DROP TABLE t,t2,t3; --echo # Bigger REPLACE ... AS SELECT test +SET GLOBAL wsrep_mode=REPLICATE_MYISAM; CREATE TABLE t1(id int not null primary key ,b int) ENGINE=InnoDB; CREATE TABLE t2(id int not null primary key ,b int) ENGINE=MyISAM; CREATE TABLE t3(id int not null primary key ,b int) ENGINE=Aria; @@ -95,7 +96,7 @@ SELECT COUNT(*) AS EXPECT_1000 FROM t8; --connection node_2 --let $wait_condition = SELECT COUNT(*) = 8 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't_' --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 1000 FROM test.t8; +--let $wait_condition = SELECT COUNT(*) = 1000 FROM test.t7; --source include/wait_condition.inc SELECT COUNT(*) AS EXPECT_1000 FROM t1; @@ -105,7 +106,7 @@ SELECT COUNT(*) AS EXPECT_1000 FROM t4; SELECT COUNT(*) AS EXPECT_1000 FROM t5; SELECT COUNT(*) AS EXPECT_1000 FROM t6; SELECT COUNT(*) AS EXPECT_1000 FROM t7; -SELECT COUNT(*) AS EXPECT_1000 FROM t8; +SELECT COUNT(*) AS EXPECT_0 FROM t8; --connection node_1 DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; @@ -143,7 +144,7 @@ SELECT COUNT(*) AS EXPECT_1000 FROM t8; --connection node_2 --let $wait_condition = SELECT COUNT(*) = 8 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't_' --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 1000 FROM test.t8; +--let $wait_condition = SELECT COUNT(*) = 1000 FROM test.t7; --source include/wait_condition.inc SELECT COUNT(*) AS EXPECT_1000 FROM t1; @@ -153,7 +154,7 @@ SELECT COUNT(*) AS EXPECT_1000 FROM t4; SELECT COUNT(*) AS EXPECT_1000 FROM t5; SELECT COUNT(*) AS EXPECT_1000 FROM t6; SELECT COUNT(*) AS EXPECT_1000 FROM t7; -SELECT COUNT(*) AS EXPECT_1000 FROM t8; +SELECT COUNT(*) AS EXPECT_0 FROM t8; --connection node_1 DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; diff --git a/mysql-test/suite/galera_3nodes/r/GCF-354.result b/mysql-test/suite/galera_3nodes/r/GCF-354.result index 3fdd44fe9d3..c69de54747f 100644 --- a/mysql-test/suite/galera_3nodes/r/GCF-354.result +++ b/mysql-test/suite/galera_3nodes/r/GCF-354.result @@ -1,17 +1,20 @@ connection node_2; connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_1; connection node_2; connection node_3; connection node_2; -SET SESSION wsrep_on=OFF; +SET wsrep_on=OFF; DROP SCHEMA test; connection node_3; -SET SESSION wsrep_on=OFF; +SET wsrep_on=OFF; CREATE TABLE test.t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; connection node_1; CREATE TABLE test.t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; -INSERT INTO test.t1 values (1); +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE +1 SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value wsrep_cluster_status Primary diff --git a/mysql-test/suite/galera_3nodes/r/galera_ssl_reload.result b/mysql-test/suite/galera_3nodes/r/galera_ssl_reload.result index 1daf3bedf4f..fffc4f3f5b5 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ssl_reload.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ssl_reload.result @@ -14,3 +14,9 @@ connection node_3; # restart: with restart_parameters connection node_2; FLUSH SSL; +connection node_3; +call mtr.add_suppression("WSREP: Handshake failed: unexpected eof while reading"); +connection node_2; +call mtr.add_suppression("WSREP: Handshake failed: unexpected eof while reading"); +connection node_1; +call mtr.add_suppression("WSREP: Handshake failed: unexpected eof while reading"); diff --git a/mysql-test/suite/galera_3nodes/t/GCF-354.cnf b/mysql-test/suite/galera_3nodes/t/GCF-354.cnf index 4c5e4854606..e87e65ca58c 100644 --- a/mysql-test/suite/galera_3nodes/t/GCF-354.cnf +++ b/mysql-test/suite/galera_3nodes/t/GCF-354.cnf @@ -3,3 +3,14 @@ [mysqld] wsrep-ignore-apply-errors=0 wsrep_sync_wait=0 +loose-gcf-354=0 +wsrep-debug=1 + +[mysqld.1] +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=1G;pc.weight=4' + +[mysqld.2] +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=1G' + +[mysqld.3] +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=1G' diff --git a/mysql-test/suite/galera_3nodes/t/GCF-354.test b/mysql-test/suite/galera_3nodes/t/GCF-354.test index 44dfa3deeb7..372f6329e8e 100644 --- a/mysql-test/suite/galera_3nodes/t/GCF-354.test +++ b/mysql-test/suite/galera_3nodes/t/GCF-354.test @@ -2,9 +2,7 @@ --source include/have_innodb.inc --source include/force_restart.inc ---let $galera_connection_name = node_3 ---let $galera_server_number = 3 ---source include/galera_connect.inc +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 # Save original auto_increment_offset values. --let $node_1=node_1 @@ -16,11 +14,11 @@ # 1. Create different inconsistencies on nodes 2 and 3 # --connection node_2 -SET SESSION wsrep_on=OFF; +SET wsrep_on=OFF; DROP SCHEMA test; --connection node_3 -SET SESSION wsrep_on=OFF; +SET wsrep_on=OFF; CREATE TABLE test.t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; # # 2. The following should generate different errors on nodes 2 and 3 and @@ -29,10 +27,10 @@ CREATE TABLE test.t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; # --connection node_1 CREATE TABLE test.t1 (f1 INTEGER NOT NULL PRIMARY KEY) engine=innodb; -INSERT INTO test.t1 values (1); --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status' --source include/wait_condition.inc SHOW STATUS LIKE 'wsrep_cluster_status'; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.cnf b/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.cnf index 65d1599268d..d4c654e2bf8 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.cnf @@ -1,10 +1,14 @@ !include ../galera_3nodes.cnf +[mysqld] +wsrep-debug=1 +loose-galera-ssl-reload=1 + [mysqld.1] -wsrep_provider_options='base_port=@mysqld.1.#galera_port;socket.ssl=yes;socket.ssl_ca=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.root.crt;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.1.crt;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.1.key' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;socket.ssl=yes;socket.ssl_ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/client-cert.pem;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/client-key.pem' [mysqld.2] -wsrep_provider_options='base_port=@mysqld.2.#galera_port;socket.ssl=yes;socket.ssl_ca=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.root.crt;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.1.crt;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.1.key' +wsrep_provider_options='base_port=@mysqld.2.#galera_port;socket.ssl=yes;socket.ssl_ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/client-cert.pem;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/client-key.pem' [mysqld.3] -wsrep_provider_options='base_port=@mysqld.3.#galera_port;socket.ssl=yes;socket.ssl_ca=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.root.crt;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.1.crt;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/galera_certs/galera.1.key' +wsrep_provider_options='base_port=@mysqld.3.#galera_port;socket.ssl=yes;socket.ssl_ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/client-cert.pem;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/client-key.pem' diff --git a/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.test b/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.test index 714d4b3f75c..f7bed23294d 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ssl_reload.test @@ -5,6 +5,7 @@ --source include/galera_cluster.inc --source include/have_openssl.inc --source include/have_ssl_communication.inc +--source include/force_restart.inc --let $galera_version=26.4.8 source ../../wsrep/include/check_galera_version.inc; @@ -31,22 +32,22 @@ let $ssl_cert = $MYSQLTEST_VARDIR/tmp/ssl_cert.pem; let $ssl_key = $MYSQLTEST_VARDIR/tmp/ssl_key.pem; let $ssl_ca = $MYSQLTEST_VARDIR/tmp/ssl_ca.pem; -copy_file std_data/galera_certs/galera.root.crt $ssl_ca; -copy_file std_data/galera_certs/galera.1.crt $ssl_cert; -copy_file std_data/galera_certs/galera.1.key $ssl_key; +copy_file std_data/cacert.pem $ssl_ca; +copy_file std_data/client-cert.pem $ssl_cert; +copy_file std_data/client-key.pem $ssl_key; --connection node_2 --source include/shutdown_mysqld.inc --let $restart_noprint=1 ---let $restart_parameters = --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1 --wsrep_provider_options=base_port=$NODE_GALERAPORT_2;socket.ssl=yes;socket.ssl_ca=$MYSQL_TEST_DIR/std_data/galera_certs/galera.root.crt;socket.ssl_cert=$MYSQLTEST_VARDIR/tmp/ssl_cert.pem;socket.ssl_key=$MYSQLTEST_VARDIR/tmp/ssl_key.pem +--let $restart_parameters = --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1 --wsrep_provider_options=base_port=$NODE_GALERAPORT_2;socket.ssl=yes;socket.ssl_ca=$MYSQL_TEST_DIR/std_data/cacert.pem;socket.ssl_cert=$MYSQLTEST_VARDIR/tmp/ssl_cert.pem;socket.ssl_key=$MYSQLTEST_VARDIR/tmp/ssl_key.pem --source include/start_mysqld.inc --source include/galera_wait_ready.inc # Set certificate and key and reload by setting directly `wsrep_provider_options` remove_file $ssl_cert; remove_file $ssl_key; -copy_file std_data/galera_certs/galera.2.crt $ssl_cert; -copy_file std_data/galera_certs/galera.2.key $ssl_key; +copy_file std_data/client-cert.pem $ssl_cert; +copy_file std_data/client-key.pem $ssl_key; SET GLOBAL wsrep_provider_options = 'socket.ssl_reload=1'; --connection node_3 @@ -67,5 +68,12 @@ remove_file $ssl_ca; remove_file $ssl_cert; remove_file $ssl_key; +--connection node_3 +call mtr.add_suppression("WSREP: Handshake failed: unexpected eof while reading"); +--connection node_2 +call mtr.add_suppression("WSREP: Handshake failed: unexpected eof while reading"); +--connection node_1 +call mtr.add_suppression("WSREP: Handshake failed: unexpected eof while reading"); + # Restore original auto_increment_offset values. --source ../galera/include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index 95ef8c1989b..21456461c47 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -519,6 +519,15 @@ COUNT(*) 1 DROP TABLE t1; # End of 10.4 tests -SET GLOBAL innodb_stats_persistent = @save_stats_persistent; +# +# MDEV-29010 Table cannot be loaded after instant ALTER +# +CREATE TABLE t1 (a CHAR(255), b INT, +c INT as (b) VIRTUAL)ENGINE=InnoDB CHARACTER SET utf32; +ALTER TABLE t1 DROP COLUMN a; +ALTER TABLE t1 DROP COLUMN c; +DROP TABLE t1; +# End of 10.5 tests # End of 10.6 tests ALTER DATABASE test CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 9cec8ed7e96..973980e4fca 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -557,8 +557,19 @@ DROP TABLE t1; --echo # End of 10.4 tests -SET GLOBAL innodb_stats_persistent = @save_stats_persistent; +--echo # +--echo # MDEV-29010 Table cannot be loaded after instant ALTER +--echo # +CREATE TABLE t1 (a CHAR(255), b INT, + c INT as (b) VIRTUAL)ENGINE=InnoDB CHARACTER SET utf32; +ALTER TABLE t1 DROP COLUMN a; +ALTER TABLE t1 DROP COLUMN c; +DROP TABLE t1; + +--echo # End of 10.5 tests --echo # End of 10.6 tests --source include/test_db_charset_restore.inc + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb_fts/r/multiple_index.result b/mysql-test/suite/innodb_fts/r/multiple_index.result new file mode 100644 index 00000000000..1750fb06ac7 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/multiple_index.result @@ -0,0 +1,210 @@ +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB STATS_PERSISTENT=0; +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx_1 (a); +ALTER TABLE t1 ADD FULLTEXT INDEX idx_2 (b); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` varchar(200) DEFAULT NULL, + `b` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx_1` (`a`), + FULLTEXT KEY `idx_2` (`b`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci STATS_PERSISTENT=0 +START TRANSACTION; +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +ROLLBACK; +SELECT * FROM t1 WHERE MATCH (a) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(a) AGAINST("+mysql +Tutorial" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(b) AGAINST("+Tutorial" IN BOOLEAN MODE); +id a b +3 Optimizing MySQL In this tutorial we will show ... +select * from t1 where MATCH(b) AGAINST("+stands +(DataBase)" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(b) AGAINST("+DataBase -(comparison)" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select *, MATCH(a) AGAINST("Optimizing MySQL" IN BOOLEAN MODE) as x from t1; +id a b x +1 MySQL Tutorial DBMS stands for DataBase ... 0.000000001885928302414186 +2 How To Use MySQL Well After you went through a ... 0.000000001885928302414186 +3 Optimizing MySQL In this tutorial we will show ... 0.22764469683170319 +select *, MATCH(b) AGAINST("collections support" IN BOOLEAN MODE) as x from t1; +id a b x +1 MySQL Tutorial DBMS stands for DataBase ... 0 +2 How To Use MySQL Well After you went through a ... 0 +3 Optimizing MySQL In this tutorial we will show ... 0 +select * from t1 where MATCH a AGAINST ("+Optimiz* +Optimiz*" IN BOOLEAN MODE); +id a b +3 Optimizing MySQL In this tutorial we will show ... +select * from t1 where MATCH b AGAINST ('"DBMS stands"' IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH b AGAINST ('"DBMS STANDS"' IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(b) AGAINST ("DataBase" WITH QUERY EXPANSION); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(a) AGAINST ("Security" WITH QUERY EXPANSION); +id a b +ALTER TABLE t1 DROP INDEX idx_1; +ALTER TABLE t1 DROP INDEX idx_2; +ALTER TABLE t1 ADD FULLTEXT INDEX idx_1 (a); +ALTER TABLE t1 ADD FULLTEXT INDEX idx_2 (b); +SELECT * FROM t1 WHERE MATCH (a) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(a) AGAINST("+mysql +Tutorial" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(b) AGAINST("+Tutorial" IN BOOLEAN MODE); +id a b +3 Optimizing MySQL In this tutorial we will show ... +select * from t1 where MATCH(b) AGAINST("+stands +(DataBase)" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(b) AGAINST("+DataBase -(comparison)" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select *, MATCH(a) AGAINST("Optimizing MySQL" IN BOOLEAN MODE) as x from t1; +id a b x +1 MySQL Tutorial DBMS stands for DataBase ... 0.000000001885928302414186 +2 How To Use MySQL Well After you went through a ... 0.000000001885928302414186 +3 Optimizing MySQL In this tutorial we will show ... 0.22764469683170319 +select *, MATCH(b) AGAINST("collections support" IN BOOLEAN MODE) as x from t1; +id a b x +1 MySQL Tutorial DBMS stands for DataBase ... 0 +2 How To Use MySQL Well After you went through a ... 0 +3 Optimizing MySQL In this tutorial we will show ... 0 +select * from t1 where MATCH a AGAINST ("+Optimiz* +Optimiz*" IN BOOLEAN MODE); +id a b +3 Optimizing MySQL In this tutorial we will show ... +select * from t1 where MATCH b AGAINST ('"DBMS stands"' IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH b AGAINST ('"DBMS STANDS"' IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(b) AGAINST ("DataBase" WITH QUERY EXPANSION); +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +select * from t1 where MATCH(a) AGAINST ("Security" WITH QUERY EXPANSION); +id a b +INSERT INTO t1 (a,b) VALUES ('test query expansion','for database ...'); +INSERT INTO t1 (a,b) VALUES +('test proximity search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test proximity fts search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test more of proximity for fts search, test, more proximity and phrase', +'search, with proximity innodb'); +SELECT * FROM t1 +WHERE MATCH (a) +AGAINST ('"proximity search"@3' IN BOOLEAN MODE); +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a) +AGAINST ('"proximity search"@2' IN BOOLEAN MODE); +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (b) +AGAINST ('"proximity innodb"@4' IN BOOLEAN MODE); +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more of proximity for fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a) +AGAINST ('"test proximity"@3' IN BOOLEAN MODE); +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more of proximity for fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a) +AGAINST ('"more test proximity"@3' IN BOOLEAN MODE); +id a b +10 test more of proximity for fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a) +AGAINST ('"more test proximity"@2' IN BOOLEAN MODE); +id a b +SELECT * FROM t1 +WHERE MATCH (a) +AGAINST ('"more fts proximity"@02' IN BOOLEAN MODE); +id a b +SELECT * FROM t1 WHERE CONCAT(t1.a,t1.b) IN ( +SELECT CONCAT(a,b) FROM t1 AS t2 WHERE +MATCH (t2.a) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +) OR t1.id = 3 ; +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t1 WHERE CONCAT(t1.a,t1.b) IN ( +SELECT CONCAT(a,b) FROM t1 AS t2 +WHERE MATCH (t2.a) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +AND t2.id != 3) ; +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +SELECT * FROM t1 WHERE id IN (SELECT MIN(id) FROM t1 WHERE +MATCH (b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)) OR id = 3 ; +id a b +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t1 WHERE id NOT IN (SELECT MIN(id) FROM t1 +WHERE MATCH (b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)) ; +id a b +1 MySQL Tutorial DBMS stands for DataBase ... +2 How To Use MySQL Well After you went through a ... +7 test query expansion for database ... +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more of proximity for fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 WHERE EXISTS (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +AND t1.id = t2.id) ; +id a b +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t1 WHERE NOT EXISTS (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.a) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +AND t1.id = t2.id) ; +id a b +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +7 test query expansion for database ... +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more of proximity for fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 WHERE t1.id = (SELECT MAX(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a) AGAINST ('"proximity search"@3' IN BOOLEAN MODE)); +id a b +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +SELECT * FROM t1 WHERE t1.id > (SELECT MIN(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.b) AGAINST ('"proximity innodb"@3' IN BOOLEAN MODE)); +id a b +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more of proximity for fts search, test, more proximity and phrase search, with proximity innodb +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/plugin_debug.result b/mysql-test/suite/innodb_fts/r/plugin_debug.result new file mode 100644 index 00000000000..6f12e2b0809 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/plugin_debug.result @@ -0,0 +1,318 @@ +INSTALL PLUGIN simple_parser SONAME 'mypluglib'; +# Test Part 2: Create Index Test(CREATE TABLE WITH FULLTEXT INDEX) +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title, body) WITH PARSER simple_parser +) ENGINE=InnoDB; +INSERT INTO articles (title, body) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'), +('Go MySQL Tricks','How to use full text search engine'); +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('mysql'); +id title body +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('will go'); +id title body +# Test plugin parser tokenizer difference +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full-text'); +id title body +4 1001 MySQL Tricks How to use full-text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full text'); +id title body +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); +id title body +DROP TABLE articles; +# Test Part 3: Row Merge Create Index Test(ALTER TABLE ADD FULLTEXT INDEX) +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT +) ENGINE=InnoDB; +INSERT INTO articles (title, body) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'), +('Go MySQL Tricks','How to use full text search engine'); +ALTER TABLE articles ADD FULLTEXT INDEX (title, body) WITH PARSER simple_parser; +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('mysql'); +id title body +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('will go'); +id title body +# Test plugin parser tokenizer difference +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full-text'); +id title body +4 1001 MySQL Tricks How to use full-text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full text'); +id title body +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full-text' WITH QUERY EXPANSION); +id title body +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +2 How To Use MySQL Well After you went through a ... +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full text' WITH QUERY EXPANSION); +id title body +5 Go MySQL Tricks How to use full text search engine +4 1001 MySQL Tricks How to use full-text search engine +2 How To Use MySQL Well After you went through a ... +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); +id title body +DROP TABLE articles; +# Test Part 3 END +SET SESSION debug="+d,fts_instrument_use_default_parser"; +# Test Part 4: Create Index Test with Default/Internal Parser +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title, body) WITH PARSER simple_parser +) ENGINE=InnoDB; +INSERT INTO articles (title, body) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'), +('Go MySQL Tricks','How to use full text search engine'); +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('mysql'); +id title body +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('will go'); +id title body +# Test plugin parser tokenizer difference +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full-text'); +id title body +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full text'); +id title body +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +# simple parser st_mysql_ftparser_boolean_info doesn't +# store position of every word in boolean metadata. +# This leads to empty result +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); +id title body +DROP TABLE articles; +# Test Part 5: Row Merge Create Index Test with Default/Internal Parser +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT +) ENGINE=InnoDB; +INSERT INTO articles (title, body) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'), +('Go MySQL Tricks','How to use full text search engine'); +ALTER TABLE articles ADD FULLTEXT INDEX (title, body) WITH PARSER simple_parser; +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('mysql'); +id title body +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('will go'); +id title body +# Test plugin parser tokenizer difference +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full-text'); +id title body +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('full text'); +id title body +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine +# simple parser st_mysql_ftparser_boolean_info doesn't +# store position of every word in boolean metadata. +# This leads to empty result +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); +id title body +DROP TABLE articles; +# Test Part 6: Test Query Parser with Default/Internal Parser +SET GLOBAL innodb_ft_enable_diag_print = 1; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title, body) WITH PARSER simple_parser +) ENGINE=InnoDB; +INSERT INTO articles (title, body) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('MySQL Tutorial','DBMS stands for MySQL good one DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'); +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('+mysql -database' IN BOOLEAN MODE); +id title body +3 How To Use MySQL Well After you went through a ... +4 Optimizing MySQL In this tutorial we will show ... +5 1001 MySQL Tricks How to use full-text search engine +SELECT * FROM articles WHERE +MATCH(title, body) AGAINST('>mysql (SELECT MIN(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.b) AGAINST ('"proximity innodb"@3' IN BOOLEAN MODE)); + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/plugin_debug.test b/mysql-test/suite/innodb_fts/t/plugin_debug.test new file mode 100644 index 00000000000..4bf6d98d883 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/plugin_debug.test @@ -0,0 +1,308 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_simple_parser.inc + +# Install fts parser plugin +INSTALL PLUGIN simple_parser SONAME 'mypluglib'; + +-- echo # Test Part 2: Create Index Test(CREATE TABLE WITH FULLTEXT INDEX) +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title, body) WITH PARSER simple_parser + ) ENGINE=InnoDB; + +INSERT INTO articles (title, body) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','How to use full-text search engine'), + ('Go MySQL Tricks','How to use full text search engine'); + +# Simple term search +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('mysql'); + +# Test stopword and word len less than fts_min_token_size +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('will go'); + +-- echo # Test plugin parser tokenizer difference +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full-text'); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full text'); + +# No result here, we get '"mysql' 'database"' by simple parser +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); + +DROP TABLE articles; + +-- echo # Test Part 3: Row Merge Create Index Test(ALTER TABLE ADD FULLTEXT INDEX) +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT + ) ENGINE=InnoDB; + +INSERT INTO articles (title, body) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','How to use full-text search engine'), + ('Go MySQL Tricks','How to use full text search engine'); + +# Create fulltext index +ALTER TABLE articles ADD FULLTEXT INDEX (title, body) WITH PARSER simple_parser; + +# Simple term search +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('mysql'); + +# Test stopword and word len less than fts_min_token_size +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('will go'); + +-- echo # Test plugin parser tokenizer difference +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full-text'); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full text'); + +# Test query expansion +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full-text' WITH QUERY EXPANSION); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full text' WITH QUERY EXPANSION); + +# No result here, we get '"mysql' 'database"' by simple parser +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); + +DROP TABLE articles; +-- echo # Test Part 3 END + +# Use default parser +SET SESSION debug="+d,fts_instrument_use_default_parser"; + +-- echo # Test Part 4: Create Index Test with Default/Internal Parser +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title, body) WITH PARSER simple_parser + ) ENGINE=InnoDB; + +INSERT INTO articles (title, body) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','How to use full-text search engine'), + ('Go MySQL Tricks','How to use full text search engine'); + +# Simple term search +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('mysql'); + +# Test stopword and word len less than fts_min_token_size +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('will go'); + +-- echo # Test plugin parser tokenizer difference +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full-text'); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full text'); + +# Phrase search +--echo # simple parser st_mysql_ftparser_boolean_info doesn't +--echo # store position of every word in boolean metadata. +--echo # This leads to empty result +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); + +DROP TABLE articles; + +# Disable query parse using plugin parser +-- echo # Test Part 5: Row Merge Create Index Test with Default/Internal Parser +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT + ) ENGINE=InnoDB; + +INSERT INTO articles (title, body) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','How to use full-text search engine'), + ('Go MySQL Tricks','How to use full text search engine'); + +# Create fulltext index +ALTER TABLE articles ADD FULLTEXT INDEX (title, body) WITH PARSER simple_parser; + +# Simple term search +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('mysql'); + +# Test stopword and word len less than fts_min_token_size +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('will go'); + +-- echo # Test plugin parser tokenizer difference +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full-text'); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('full text'); + +# Phrase search +--echo # simple parser st_mysql_ftparser_boolean_info doesn't +--echo # store position of every word in boolean metadata. +--echo # This leads to empty result +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); + +DROP TABLE articles; + +-- echo # Test Part 6: Test Query Parser with Default/Internal Parser +let $innodb_ft_enable_diag_print_orig = `SELECT @@innodb_ft_enable_diag_print`; +# Enable diag print to print query parse tree +SET GLOBAL innodb_ft_enable_diag_print = 1; + +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title, body) WITH PARSER simple_parser + ) ENGINE=InnoDB; + +INSERT INTO articles (title, body) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('MySQL Tutorial','DBMS stands for MySQL good one DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','How to use full-text search engine'); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('+mysql -database' IN BOOLEAN MODE); + +SELECT * FROM articles WHERE + MATCH(title, body) AGAINST('>mysql field[0]->ptr >= table->record[0] && +# table->field[0]->ptr <= table->record[0] + table->s->reclength' failed in +# void handler::assert_icp_limitations(uchar*) +# +SET sql_mode=''; +CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 SELECT 1 FROM seq_1_to_2 ; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 SELECT 1 UNION SELECT 1; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result index 7e071ed041c..5be71a0a263 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result @@ -215,6 +215,25 @@ INDEX(vc(32)) ); DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; DROP TABLE t1; +SET sql_mode=''; +CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 SELECT 1 FROM seq_1_to_2 ; +Warnings: +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +SELECT * FROM t1; +a +1 +1 +DROP TABLE t1; +CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 SELECT 1 UNION SELECT 1; +Warnings: +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +SELECT * FROM t1; +a +1 +DROP TABLE t1; # # MDEV-11737 Failing assertion: block->magic_n == MEM_BLOCK_MAGIC_N # diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index 9e0e130912e..248987f1ce0 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -209,6 +209,25 @@ INDEX(vc(32)) ); DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; DROP TABLE t1; +SET sql_mode=''; +CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 SELECT 1 FROM seq_1_to_2 ; +Warnings: +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +SELECT * FROM t1; +a +1 +1 +DROP TABLE t1; +CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 SELECT 1 UNION SELECT 1; +Warnings: +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +SELECT * FROM t1; +a +1 +DROP TABLE t1; # # Original test # diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index 079ceb975dd..ce4b45319bc 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -16,6 +16,9 @@ SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format STATEMENT CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +Warnings: +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW SET binlog_format=MIXED; Warnings: Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED @@ -26,9 +29,14 @@ SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format MIXED CREATE TABLE IF NOT EXISTS test.t2 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +Warnings: +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW SET binlog_format=ROW; SHOW WARNINGS; Level Code Message +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW +Warning 1105 Galera does not support binlog_format = MIXED in CREATE TABLE [SELECT|REPLACE] forcing ROW SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW diff --git a/mysys_ssl/openssl.c b/mysys_ssl/openssl.c index 8adaeae4069..e0271817309 100644 --- a/mysys_ssl/openssl.c +++ b/mysys_ssl/openssl.c @@ -47,12 +47,25 @@ static void *coc_malloc(size_t size, const char *f __attribute__((unused)), return malloc(size); } +static void *coc_realloc(void *addr, size_t num, + const char *file __attribute__((unused)), + int line __attribute__((unused))) +{ + return realloc(addr, num); +} + +static void coc_free(void *addr, const char *file __attribute__((unused)), + int line __attribute__((unused))) +{ + free(addr); +} + int check_openssl_compatibility() { EVP_CIPHER_CTX *evp_ctx; EVP_MD_CTX *md5_ctx; - if (!CRYPTO_set_mem_functions(coc_malloc, NULL, NULL)) + if (!CRYPTO_set_mem_functions(coc_malloc, coc_realloc, coc_free)) return 0; testing= 1; diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 0d92a3c05b8..7639f0bbda8 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -100,10 +100,9 @@ check_pid_and_port() local busy=0 if [ $lsof_available -ne 0 ]; then - port_info=$(lsof -Pnl -i ":$port" 2>/dev/null | \ - grep -F '(LISTEN)') + port_info=$(lsof -Pnl -i ":$port" 2>/dev/null | grep -F '(LISTEN)') echo "$port_info" | \ - grep -q -E "[[:space:]](\\*|\\[?::\\]?):$port[[:space:]]" && busy=1 + grep -q -E "[[:space:]]\\[?(\\*|[[:xdigit:]]*(:[[:xdigit:]]*)+)(\\](%[^:]+)?)?:$port[[:space:]]" && busy=1 else local filter='([^[:space:]]+[[:space:]]+){4}[^[:space:]]+' if [ $sockstat_available -ne 0 ]; then @@ -122,7 +121,7 @@ check_pid_and_port() grep -F 'users:(' | grep -o -E "$filter") fi echo "$port_info" | \ - grep -q -E "[[:space:]](\\*|\\[?::\\]?):$port\$" && busy=1 + grep -q -E "[[:space:]]\\[?(\\*|[[:xdigit:]]*(:[[:xdigit:]]*)+)(\\](%[^:]+)?)?:$port\$" && busy=1 fi if [ $busy -eq 0 ]; then diff --git a/sql/contributors.h b/sql/contributors.h index bc8ba4eabbb..1a887ef3d25 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -36,20 +36,44 @@ struct show_table_contributors_st { */ struct show_table_contributors_st show_table_contributors[]= { - /* MariaDB foundation sponsors, in contribution, size , time order */ + /* MariaDB Foundation sponsors, alphabetical by tier */ + {"Amazon", "https://www.amazon.com/", "Diamond Sponsor of the MariaDB Foundation"}, + {"Acronis", "https://www.acronis.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"Alibaba Cloud", "https://www.alibabacloud.com/", "Platinum Sponsor of the MariaDB Foundation"}, - {"Tencent Cloud", "https://cloud.tencent.com", "Platinum Sponsor of the MariaDB Foundation"}, - {"Microsoft", "https://microsoft.com/", "Platinum Sponsor of the MariaDB Foundation"}, - {"MariaDB Corporation", "https://mariadb.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"}, - {"ServiceNow", "https://servicenow.com", "Platinum Sponsor of the MariaDB Foundation"}, - {"Intel", "https://www.intel.com", "Platinum Sponsor of the MariaDB Foundation"}, - {"SIT", "https://sit.org", "Platinum Sponsor of the MariaDB Foundation"}, - {"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"}, - {"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"}, - {"IBM", "https://www.ibm.com", "Gold Sponsor of the MariaDB Foundation"}, - {"Automattic", "https://automattic.com", "Silver Sponsor of the MariaDB Foundation"}, + {"Csignal_ddl_recovery_done) - hton->signal_ddl_recovery_done(hton); + ret= hton->signal_ddl_recovery_done(hton); DBUG_RETURN(ret); diff --git a/sql/item.h b/sql/item.h index 19a2e145c45..4de5686fb02 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3773,6 +3773,10 @@ public: return &type_handler_null; return field->type_handler(); } + uint32 character_octet_length() const override + { + return field->character_octet_length(); + } Field *create_tmp_field_from_item_field(MEM_ROOT *root, TABLE *new_table, Item_ref *orig_item, const Tmp_field_param *param); @@ -4941,6 +4945,9 @@ public: Item_string_sys(THD *thd, const char *str): Item_string(thd, str, (uint) strlen(str), system_charset_info_for_i_s) { } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -4955,6 +4962,9 @@ public: Item_string(thd, str, (uint) strlen(str), &my_charset_latin1, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII) { } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -4991,6 +5001,9 @@ public: // require fix_fields() to be re-run for every statement. return mark_unsupported_function(func_name.str, arg, VCOL_TIME_FUNC); } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -5008,6 +5021,9 @@ public: { return mark_unsupported_function("safe_string", arg, VCOL_IMPOSSIBLE); } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -5169,6 +5185,9 @@ class Item_bin_string: public Item_hex_hybrid public: Item_bin_string(THD *thd, const char *str, size_t str_length); void print(String *str, enum_query_type query_type) override; + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -5485,6 +5504,9 @@ public: cached_time.copy_to_mysql_time(ltime); return (null_value= false); } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -5858,6 +5880,10 @@ public: { return (*ref)->type_handler(); } const Type_handler *real_type_handler() const override { return (*ref)->real_type_handler(); } + uint32 character_octet_length() const override + { + return Item_ref::real_item()->character_octet_length(); + } Field *get_tmp_table_field() override { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd) override; @@ -5898,9 +5924,10 @@ public: { (*ref)->save_in_field(result_field, no_conversions); } - Item *real_item() override + Item *real_item() override { return ref ? (*ref)->real_item() : this; } + const Item *real_item() const { - return ref ? (*ref)->real_item() : this; + return const_cast(this)->Item_ref::real_item(); } const Type_extra_attributes type_extra_attributes() const override { @@ -6984,7 +7011,9 @@ public: description */ bool associate_with_target_field(THD *thd, Item_field *field) override; - + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item* do_build_clone(THD *thd) const override { return get_copy(thd); } private: bool tie_field(THD *thd); }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1efd7958a76..d1a98da4a08 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1893,6 +1893,16 @@ longlong Item_func_eq::val_int() } +Item *Item_func_eq::do_build_clone(THD *thd) const +{ + /* + Clone the parent and cast to the child class since there is nothing + specific for Item_func_eq + */ + return (Item_func_eq*) Item_bool_rowready_func2::do_build_clone(thd); +} + + /** Same as Item_func_eq, but NULL = NULL. */ bool Item_func_equal::fix_length_and_dec(THD *thd) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 48c5a4d0114..4ca70931fb3 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -810,11 +810,12 @@ public: uint in_equality_no; uint exists2in_reserved_items() override { return 1; }; friend class Arg_comparator; - Item *do_get_copy(THD *thd) const override - { return get_item_copy(thd, this); } Item* date_conds_transformer(THD *thd, uchar *arg) override { return do_date_conds_transformation(thd, this); } Item* varchar_upper_cmp_transformer(THD *thd, uchar *arg) override; + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override; }; class Item_func_equal final :public Item_bool_rowready_func2 @@ -2457,7 +2458,7 @@ public: Item *do_build_clone(THD *thd) const override { Item_func_case_simple *clone= (Item_func_case_simple *) - Item_func_case::build_clone(thd); + Item_func_case::do_build_clone(thd); uint ncases= when_count(); if (clone && clone->Predicant_to_list_comparator::init_clone(thd, ncases)) return NULL; diff --git a/sql/log.cc b/sql/log.cc index 373c8694d76..34f9ad745fc 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -9823,6 +9823,25 @@ static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, #ifndef EMBEDDED_LIBRARY +#ifndef _WIN32 +#define fprintf_stderr(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +/* + On Windows, if FILE* is unbuffered, fprintf() writes output byte by byte. + This is suboptimal for printing to error log, we want full message at once. +*/ +#define fprintf_stderr(format, ...) \ + do \ + { \ + char buf[256]; \ + size_t len= snprintf(buf, sizeof(buf), format, __VA_ARGS__); \ + if (len >= sizeof(buf)) \ + fprintf(stderr, format, __VA_ARGS__); \ + else \ + fwrite(buf, len, 1, stderr); \ + } while (0) +#endif + static void print_buffer_to_file(enum loglevel level, const char *buffer, size_t length) { @@ -9856,7 +9875,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer, localtime_r(&skr, &tm_tmp); start=&tm_tmp; - fprintf(stderr, "%d-%02d-%02d %2d:%02d:%02d %lu [%s] %.*s%.*s\n", + fprintf_stderr( "%d-%02d-%02d %2d:%02d:%02d %lu [%s] %.*s%.*s\n", start->tm_year + 1900, start->tm_mon+1, start->tm_mday, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 44976c41ccc..b045bf14cd9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9246,10 +9246,22 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, if (!result && triggers) { + void *save_bulk_param= thd->bulk_param; + /* + Reset the sentinel thd->bulk_param in order not to consume the next + values of a bound array in case one of statement executed by + the trigger's body is INSERT statement. + */ + thd->bulk_param= nullptr; + if (triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE) || not_null_fields_have_null_values(table)) + { + thd->bulk_param= save_bulk_param; return TRUE; + } + thd->bulk_param= save_bulk_param; /* Re-calculate virtual fields to cater for cases when base columns are diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 74b44886ffa..13818813574 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -6670,6 +6670,24 @@ int THD::decide_logging_format(TABLE_LIST *tables) } set_current_stmt_binlog_format_row(); } + + /* If user has requested binlog_format STMT OR MIXED + in CREATE TABLE [SELECT|REPLACE] we will fall back + to ROW. + + Note that we can't use local binlog_format variable + here because wsrep_binlog_format sets it to ROW. + */ + if (wsrep_ctas && variables.binlog_format != BINLOG_FORMAT_ROW) + { + push_warning_printf(this, Sql_condition::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, + "Galera does not support binlog_format = %s " + "in CREATE TABLE [SELECT|REPLACE] forcing ROW", + binlog_format == BINLOG_FORMAT_STMT ? + "STMT" : "MIXED"); + set_current_stmt_binlog_format_row(); + } #endif /* WITH_WSREP */ if (WSREP_EMULATE_BINLOG_NNULL(this) || diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 88c93f829b1..f87776e13f1 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -814,13 +814,17 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd) delete_history); if (delete_record) { + void *save_bulk_param= thd->bulk_param; + thd->bulk_param= nullptr; if (!delete_history && table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) { error= 1; + thd->bulk_param= save_bulk_param; break; } + thd->bulk_param= save_bulk_param; // no LIMIT / OFFSET if (returning && result->send_data(returning->item_list) < 0) @@ -851,13 +855,16 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd) if (likely(!error)) { deleted++; + thd->bulk_param= nullptr; if (!delete_history && table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) { error= 1; + thd->bulk_param= save_bulk_param; break; } + thd->bulk_param= save_bulk_param; if (!--limit && using_limit) { error= -1; @@ -918,6 +925,7 @@ cleanup: { thd->lex->current_select->save_leaf_tables(thd); thd->lex->current_select->leaf_tables_saved= true; + thd->lex->current_select->first_cond_optimization= false; } delete deltempfile; diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 76ed0ca2248..2fb1133892f 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -309,14 +309,27 @@ Diagnostics_area::reset_diagnostics_area() m_message[0]= '\0'; Sql_state_errno::clear(); Sql_user_condition_identity::clear(); - m_affected_rows= 0; m_last_insert_id= 0; - m_statement_warn_count= 0; + if (!is_bulk_op()) + { + m_affected_rows= 0; + m_statement_warn_count= 0; + } #endif get_warning_info()->clear_error_condition(); set_is_sent(false); /** Tiny reset in debug mode to see garbage right away */ - m_status= DA_EMPTY; + if (!is_bulk_op()) + /* + For BULK DML operations (e.g. UPDATE) the data member m_status + has the value DA_OK_BULK. Keep this value in order to handle + m_affected_rows, m_statement_warn_count in correct way. Else, + the number of rows and the number of warnings affected by + the last statement executed as part of a trigger fired by the dml + (e.g. UPDATE statement fires a trigger on AFTER UPDATE) would counts + rows modified by trigger's statement. + */ + m_status= DA_EMPTY; DBUG_VOID_RETURN; } diff --git a/sql/sql_error.h b/sql/sql_error.h index 21161cb2e6a..4751444e2b6 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -1097,6 +1097,11 @@ public: return m_affected_rows; } + void set_message(const char *msg) + { + strmake_buf(m_message, msg); + } + ulonglong last_insert_id() const { DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e14b1c7ef4a..61ac5030355 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1063,19 +1063,11 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, */ restore_record(table,s->default_values); // Get empty record table->reset_default_fields(); - /* - Reset the sentinel thd->bulk_param in order not to consume the next - values of a bound array in case one of statement executed by - the trigger's body is INSERT statement. - */ - void *save_bulk_param= thd->bulk_param; - thd->bulk_param= nullptr; if (unlikely(fill_record_n_invoke_before_triggers(thd, table, fields, *values, 0, TRG_EVENT_INSERT))) { - thd->bulk_param= save_bulk_param; if (values_list.elements != 1 && ! thd->is_error()) { info.records++; @@ -1089,7 +1081,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, error=1; break; } - thd->bulk_param= save_bulk_param; } else { @@ -1389,7 +1380,18 @@ values_loop_end: */ if (returning) result->send_eof(); - else + else if (!(thd->in_sub_stmt & SUB_STMT_TRIGGER)) + /* + Set the status and the number of affected rows in Diagnostics_area + only in case the INSERT statement is not processed as part of a trigger + invoked by some other DML statement. Else we would result in incorrect + number of affected rows for bulk DML operations, e.g. the UPDATE + statement (called via PS protocol). It would happen since the data + member Diagnostics_area::m_affected_rows modified twice per DML + statement - first time at the end of handling the INSERT statement + invoking by a trigger fired on handling the original DML statement, + and the second time at the end of handling the original DML statement. + */ my_ok(thd, info.copied + info.deleted + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? info.touched : info.updated), id); @@ -1411,7 +1413,18 @@ values_loop_end: (long) thd->get_stmt_da()->current_statement_warn_count()); if (returning) result->send_eof(); - else + else if (!(thd->in_sub_stmt & SUB_STMT_TRIGGER)) + /* + Set the status and the number of affected rows in Diagnostics_area + only in case the INSERT statement is not processed as part of a trigger + invoked by some other DML statement. Else we would result in incorrect + number of affected rows for bulk DML operations, e.g. the UPDATE + statement (called via PS protocol). It would happen since the data + member Diagnostics_area::m_affected_rows modified twice per DML + statement - first time at the end of handling the INSERT statement + invoking by a trigger fired on handling the original DML statement, + and the second time at the end of handling the original DML statement. + */ ::my_ok(thd, info.copied + info.deleted + updated, id, buff); } thd->abort_on_warning= 0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8074e034646..c6a6ede4530 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4570,7 +4570,14 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) // For !InnoDB we start TOI if it is not yet started and hope for the best if (!is_innodb && !wsrep_toi) - WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL); + { + const legacy_db_type db_type= first_table->table->file->partition_ht()->db_type; + + /* Currently we support TOI for MyISAM only. */ + if (db_type == DB_TYPE_MYISAM && + wsrep_check_mode(WSREP_MODE_REPLICATE_MYISAM)) + WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL); + } } #endif /* WITH_WSREP */ /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 335c8d84b78..9f387df3869 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3288,19 +3288,22 @@ int JOIN::optimize_stage2() which do not use aggregate functions. In such case temporary table may not be used and const condition elements may be lost during further having - condition transformation in JOIN::exec. + condition transformation. */ if (having && const_table_map && !having->with_sum_func()) { having->update_used_tables(); - having= having->remove_eq_conds(thd, &select_lex->having_value, true); - if (select_lex->having_value == Item::COND_FALSE) + if (having->const_item() && !having->is_expensive()) { - having= (Item*) Item_false; - zero_result_cause= "Impossible HAVING noticed after reading const tables"; - error= 0; - select_lex->mark_const_derived(zero_result_cause); - goto setup_subq_exit; + if (!having->val_int()) + { + having= Item_false; + zero_result_cause= "Impossible HAVING noticed after reading const tables"; + error= 0; + select_lex->mark_const_derived(zero_result_cause); + goto setup_subq_exit; + } + having= Item_true; } } diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 7ecc9adbe07..4d6d06defe4 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -751,7 +751,10 @@ void sequence_definition::adjust_values(longlong next_value) next_free_value % real_increment == offset */ - off= next_free_value % real_increment; + if (is_unsigned) + off= (ulonglong) next_free_value % real_increment; + else + off= next_free_value % real_increment; if (off < 0) off+= real_increment; to_add= (real_increment + offset - off) % real_increment; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 5626c8477f5..be9a4133219 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1300,7 +1300,7 @@ uint32 Type_numeric_attributes::find_max_octet_length(Item **item, uint nitems) { uint32 octet_length= 0; for (uint i= 0; i < nitems ; i++) - set_if_bigger(octet_length, item[i]->max_length); + set_if_bigger(octet_length, item[i]->character_octet_length()); return octet_length; } diff --git a/sql/sql_type.h b/sql/sql_type.h index beba39a1d1e..5d2021c0636 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3550,6 +3550,7 @@ public: Type_all_attributes(const Type_all_attributes &) = default; virtual ~Type_all_attributes() = default; virtual void set_type_maybe_null(bool maybe_null_arg)= 0; + virtual uint32 character_octet_length() const { return max_length; } // Returns total number of decimal digits virtual decimal_digits_t decimal_precision() const= 0; virtual Type_extra_attributes *type_extra_attributes_addr() = 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ea07caabf35..2b55fb75bed 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1063,13 +1063,19 @@ error: rows_inserted++; } + void *save_bulk_param= thd->bulk_param; + thd->bulk_param= nullptr; + if (table->triggers && unlikely(table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))) { error= 1; + thd->bulk_param= save_bulk_param; + break; } + thd->bulk_param= save_bulk_param; if (!--limit && using_limit) { @@ -1262,6 +1268,20 @@ update_end: (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated); my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, id, buff); + if (thd->get_stmt_da()->is_bulk_op()) + { + /* + Update the diagnostics message sent to a client with number of actual + rows update by the statement. For bulk UPDATE operation it should be + done after returning from my_ok() since the final number of updated + rows be knows on finishing the entire bulk update statement. + */ + my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_UPDATE_INFO), + (ulong) thd->get_stmt_da()->affected_rows(), + (ulong) thd->get_stmt_da()->affected_rows(), + (ulong) thd->get_stmt_da()->current_statement_warn_count()); + thd->get_stmt_da()->set_message(buff); + } DBUG_PRINT("info",("%ld records updated", (long) updated)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 8703ad95dae..bdedbd7bf40 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1030,6 +1030,7 @@ buf_block_init(buf_block_t* block, byte* frame) MEM_MAKE_DEFINED(&block->modify_clock, sizeof block->modify_clock); ut_ad(!block->modify_clock); MEM_MAKE_DEFINED(&block->page.lock, sizeof block->page.lock); + block->page.lock.init(); block->page.init(buf_page_t::NOT_USED, page_id_t(~0ULL)); #ifdef BTR_CUR_HASH_ADAPT MEM_MAKE_DEFINED(&block->index, sizeof block->index); @@ -2608,8 +2609,11 @@ buf_page_get_gen( would typically be around 60000 with the default innodb_undo_tablespaces=3, and less than 110000 with the maximum innodb_undo_tablespaces=127. */ + ut_d(extern bool ibuf_upgrade_was_needed;) ut_ad(mode == BUF_GET_RECOVER ? recv_recovery_is_on() || log_sys.get_lsn() < 120000 + || log_sys.get_lsn() == recv_sys.lsn + SIZE_OF_FILE_CHECKPOINT + || ibuf_upgrade_was_needed : !recv_recovery_is_on() || recv_sys.after_apply); ut_ad(!mtr || mtr->is_active()); ut_ad(mtr || mode == BUF_PEEK_IF_IN_POOL); diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index d2ac0250226..5032b11d1d0 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -814,7 +814,7 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip) break; case 1: mysql_mutex_lock(&buf_pool.flush_list_mutex); - if (const lsn_t om = bpage->oldest_modification()) { + if (ut_d(const lsn_t om =) bpage->oldest_modification()) { ut_ad(om == 1); buf_pool.delete_from_flush_list(bpage); } diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 0671d7bb0ed..84b04beae34 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -173,6 +173,7 @@ page_exists: page_zip_set_size(&bpage->zip, zip_size); bpage->zip.data = (page_zip_t*) data; + bpage->lock.init(); bpage->init(buf_page_t::READ_FIX, page_id); bpage->lock.x_lock(true); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a593077dedf..f5b1c833664 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7904,7 +7904,10 @@ set_max_autoinc: if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record, NULL)) { - DBUG_PRINT("wsrep", ("row key failed")); + WSREP_DEBUG("::write_rows::wsrep_append_keys failed THD %ld for %s.%s", + thd_get_thread_id(m_user_thd), + table->s->db.str, + table->s->table_name.str); error_result = HA_ERR_INTERNAL_ERROR; goto func_exit; } @@ -8613,8 +8616,10 @@ func_exit: Check THD-level wsrep state in that case. */ (trx->is_wsrep() || (!trx_is_started(trx) && wsrep_on(m_user_thd))) && wsrep_thd_is_local(m_user_thd) - && !wsrep_thd_ignore_table(m_user_thd)) { - DBUG_PRINT("wsrep", ("update row key")); + && !wsrep_thd_ignore_table(m_user_thd) + && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) + && (thd_sql_command(m_user_thd) != SQLCOM_LOAD || + thd_binlog_format(m_user_thd) == BINLOG_FORMAT_ROW)) { /* We use table-level exclusive key for SEQUENCES and normal key append for others. */ @@ -8626,8 +8631,10 @@ func_exit: ? WSREP_SERVICE_KEY_UPDATE : WSREP_SERVICE_KEY_EXCLUSIVE, old_row, new_row)) { - WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); - DBUG_PRINT("wsrep", ("row key failed")); + WSREP_DEBUG("::update_rows::wsrep_append_keys failed THD %ld for %s.%s", + thd_get_thread_id(m_user_thd), + table->s->db.str, + table->s->table_name.str); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } @@ -8679,7 +8686,10 @@ ha_innobase::delete_row( if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record, NULL)) { - DBUG_PRINT("wsrep", ("delete fail")); + WSREP_DEBUG("::delete_rows::wsrep_append_keys failed THD %ld for %s.%s", + thd_get_thread_id(m_user_thd), + table->s->db.str, + table->s->table_name.str); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 53c19dca63f..c92d65f7f7c 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -181,6 +181,13 @@ inline void dict_table_t::init_instant(const dict_table_t& table) auto fixed_len = dict_col_get_fixed_size( f.col, not_redundant()); + + /* Long fixed length can be treated as variable + length fields that needs external storage */ + if (fixed_len > DICT_MAX_FIXED_COL_LEN) { + fixed_len = 0; + } + field_map_it->set_dropped(); if (!f.col->is_nullable()) { field_map_it->set_not_null(); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 503623bac9a..e43b86508ed 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -602,10 +602,10 @@ public: void init(uint32_t state, page_id_t id) { ut_ad(state < REMOVE_HASH || state >= UNFIXED); + ut_ad(!lock.is_locked_or_waiting()); id_= id; zip.fix= state; oldest_modification_= 0; - lock.init(); ut_d(in_zip_hash= false); ut_d(in_free_list= false); ut_d(in_LRU_list= false); diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 38373f6bb19..8686c0f8861 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -421,8 +421,7 @@ inline void page_rec_set_n_owned(buf_block_t *block, rec_t *rec, ulint n_owned, ut_ad(block->page.frame == page_align(rec)); ut_ad(comp == (page_is_comp(block->page.frame) != 0)); - if (page_zip_des_t *page_zip= compressed - ? buf_block_get_page_zip(block) : nullptr) + if (compressed && is_buf_block_get_page_zip(block)) { ut_ad(comp); rec_set_bit_field_1(rec, n_owned, REC_NEW_N_OWNED, diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h index f952722426d..e65756097a8 100644 --- a/storage/innobase/include/srw_lock.h +++ b/storage/innobase/include/srw_lock.h @@ -39,32 +39,45 @@ template class pthread_mutex_wrapper final { pthread_mutex_t lock; +#ifdef UNIV_DEBUG + /** whether the mutex is usable; set by init(); cleared by destroy() */ + bool initialized{false}; +public: + ~pthread_mutex_wrapper() { ut_ad(!initialized); } +#endif public: void init() { + ut_ad(!initialized); + ut_d(initialized= true); if (spinloop) pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST); else pthread_mutex_init(&lock, nullptr); } - void destroy() { pthread_mutex_destroy(&lock); } + void destroy() + { + ut_ad(initialized); ut_d(initialized=false); + pthread_mutex_destroy(&lock); + } # ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP - void wr_lock() { pthread_mutex_lock(&lock); } + void wr_lock() { ut_ad(initialized); pthread_mutex_lock(&lock); } # else private: void wr_wait(); public: inline void wr_lock(); # endif - void wr_unlock() { pthread_mutex_unlock(&lock); } - bool wr_lock_try() { return !pthread_mutex_trylock(&lock); } + void wr_unlock() { ut_ad(initialized); pthread_mutex_unlock(&lock); } + bool wr_lock_try() + { ut_ad(initialized); return !pthread_mutex_trylock(&lock); } }; # ifndef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP template<> void pthread_mutex_wrapper::wr_wait(); template<> inline void pthread_mutex_wrapper::wr_lock() -{ pthread_mutex_lock(&lock); } +{ ut_ad(initialized); pthread_mutex_lock(&lock); } template<> inline void pthread_mutex_wrapper::wr_lock() { if (!wr_lock_try()) wr_wait(); } diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 7928942de8d..b2977bc3aad 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1044,13 +1044,19 @@ std::pair log_t::append_prepare(size_t size, bool ex) noexcept size_t b{spin ? lock_lsn() : buf_free.load(std::memory_order_relaxed)}; write_to_buf++; - const lsn_t l{lsn.load(std::memory_order_relaxed)}, end_lsn{l + size}; + lsn_t l{lsn.load(std::memory_order_relaxed)}, end_lsn{l + size}; if (UNIV_UNLIKELY(pmem ? (end_lsn - get_flushed_lsn(std::memory_order_relaxed)) > capacity() : b + size >= buf_size)) + { b= append_prepare_wait(b, ex, l); + /* While flushing log, we had released the lsn lock and LSN could have + progressed in the meantime. */ + l= lsn.load(std::memory_order_relaxed); + end_lsn= l + size; + } size_t new_buf_free= b + size; if (pmem && new_buf_free >= file_size) diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index fcc10f41268..34785dd6cdd 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3207,6 +3207,7 @@ static void add_fts_index(dict_table_t *table) { dict_index_t *fts_index= dict_mem_index_create( table, FTS_DOC_ID_INDEX.str, DICT_UNIQUE, 2); + fts_index->lock.SRW_LOCK_INIT(index_tree_rw_lock_key); fts_index->page= FIL_NULL; fts_index->cached= 1; fts_index->n_uniq= 1; @@ -3288,6 +3289,7 @@ static dict_table_t *build_fts_hidden_table( new_table, old_index->name, old_index->type, old_index->n_fields + is_clustered); + new_index->lock.SRW_LOCK_INIT(index_tree_rw_lock_key); new_index->id= old_index->id; new_index->n_uniq= old_index->n_uniq; new_index->type= old_index->type; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 11b8349887f..280f616163f 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1163,8 +1163,11 @@ static dberr_t srv_log_rebuild_if_needed() return srv_log_rebuild(); } +ut_d(bool ibuf_upgrade_was_needed;) + ATTRIBUTE_COLD static dberr_t ibuf_log_rebuild_if_needed() { + ut_d(ibuf_upgrade_was_needed= true;) mysql_mutex_lock(&recv_sys.mutex); recv_sys.apply(true); mysql_mutex_unlock(&recv_sys.mutex); diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc index 6c37d120f73..5db6e627590 100644 --- a/storage/innobase/sync/srw_lock.cc +++ b/storage/innobase/sync/srw_lock.cc @@ -661,6 +661,7 @@ void srw_lock_debug::destroy() ut_ad(r->empty()); delete r; } + readers_lock.destroy(); srw_lock::destroy(); } diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index abfdc9202df..5d8ba639904 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -660,6 +660,7 @@ dberr_t trx_rseg_array_init() break; } + rseg.destroy(); rseg.init(rseg_space, page_no); ut_ad(rseg.is_persistent()); err = trx_rseg_mem_restore(&rseg, &mtr); @@ -741,6 +742,7 @@ dberr_t trx_temp_rseg_create(mtr_t *mtr) mtr->commit(); return err; } + trx_sys.temp_rsegs[i].destroy(); trx_sys.temp_rsegs[i].init(fil_system.temp_space, rblock->page.id().page_no()); mtr->commit(); diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 6f4f442383e..14a980175a7 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -146,6 +146,10 @@ void trx_sys_t::create() m_initialised= true; trx_list.create(); rw_trx_hash.init(); + for (auto &rseg : temp_rsegs) + rseg.init(nullptr, FIL_NULL); + for (auto &rseg : rseg_array) + rseg.init(nullptr, FIL_NULL); } size_t trx_sys_t::history_size() @@ -224,6 +228,7 @@ static trx_rseg_t *trx_rseg_create(uint32_t space_id) ? nullptr : trx_rseg_header_create(space, rseg_id, 0, &mtr, &err)) { rseg= &trx_sys.rseg_array[rseg_id]; + rseg->destroy(); rseg->init(space, rblock->page.id().page_no()); ut_ad(rseg->is_persistent()); mtr.write<4,mtr_t::MAYBE_NOP> @@ -322,13 +327,8 @@ trx_sys_t::close() rw_trx_hash.destroy(); /* There can't be any active transactions. */ - - for (ulint i = 0; i < array_elements(temp_rsegs); ++i) { - temp_rsegs[i].destroy(); - } - for (ulint i = 0; i < array_elements(rseg_array); ++i) { - rseg_array[i].destroy(); - } + for (auto& rseg : temp_rsegs) rseg.destroy(); + for (auto& rseg : rseg_array) rseg.destroy(); ut_a(trx_list.empty()); trx_list.close(); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index ef980eccc36..ccd7b2146fb 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1828,7 +1828,7 @@ trx_print_low( /*!< in: mem_heap_get_size(trx->lock.lock_heap) */ { if (const trx_id_t id = trx->id) { - fprintf(f, "TRANSACTION " TRX_ID_FMT, trx->id); + fprintf(f, "TRANSACTION " TRX_ID_FMT, id); } else { fprintf(f, "TRANSACTION (%p)", trx); } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 69626f881f5..5e627556e7e 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -712,29 +712,32 @@ my_bool mi_killed_in_mariadb(MI_INFO *info) static int compute_vcols(MI_INFO *info, uchar *record, int keynum) { + int error= 0; /* This mutex is needed for parallel repair */ mysql_mutex_lock(&info->s->intern_lock); TABLE *table= (TABLE*)(info->external_ref); - table->move_fields(table->field, record, table->field[0]->record_ptr()); + table->move_fields(table->field, record, table->record[0]); if (keynum == -1) // update all vcols { - int error= table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_READ); + error= table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_READ); if (table->update_virtual_fields(table->file, VCOL_UPDATE_INDEXED)) error= 1; - mysql_mutex_unlock(&info->s->intern_lock); - return error; } - // update only one key - KEY *key= table->key_info + keynum; - KEY_PART_INFO *kp= key->key_part, *end= kp + key->ext_key_parts; - for (; kp < end; kp++) + else { - Field *f= table->field[kp->fieldnr - 1]; - if (f->vcol_info && !f->vcol_info->is_stored()) - table->update_virtual_field(f, false); + // update only one key + KEY *key= table->key_info + keynum; + KEY_PART_INFO *kp= key->key_part, *end= kp + key->ext_key_parts; + for (; kp < end; kp++) + { + Field *f= table->field[kp->fieldnr - 1]; + if (f->vcol_info && !f->vcol_info->is_stored()) + table->update_virtual_field(f, false); + } } + table->move_fields(table->field, table->record[0], record); mysql_mutex_unlock(&info->s->intern_lock); - return 0; + return error; } } @@ -1026,16 +1029,6 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param) table->use_all_columns(); } -void ha_myisam::restore_vcos_after_repair() -{ - if (file->s->base.reclength < file->s->vreclength) - { - table->move_fields(table->field, table->record[0], - table->field[0]->record_ptr()); - table->default_column_bitmaps(); - } -} - int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) { if (!file) return HA_ADMIN_INTERNAL_ERROR; @@ -1132,8 +1125,6 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; } - restore_vcos_after_repair(); - thd_proc_info(thd, old_proc_info); return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; } @@ -1179,8 +1170,6 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) else if (!mi_is_crashed(file) && !thd->killed) mi_mark_crashed(file); - restore_vcos_after_repair(); - return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; } @@ -1230,8 +1219,6 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) break; } - restore_vcos_after_repair(); - if (!error && start_records != file->state->records && !(check_opt->flags & T_VERY_SILENT)) { @@ -1269,8 +1256,6 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) error= repair(thd,*param,1); } - restore_vcos_after_repair(); - return error; } @@ -1737,8 +1722,6 @@ int ha_myisam::enable_indexes(key_map map, bool persist) } info(HA_STATUS_CONST); thd_proc_info(thd, save_proc_info); - - restore_vcos_after_repair(); } DBUG_RETURN(error); } diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 52d23faf3c4..526cbfb1025 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -49,7 +49,6 @@ class ha_myisam final : public handler bool can_enable_indexes; int repair(THD *thd, HA_CHECK ¶m, bool optimize); void setup_vcols_for_repair(HA_CHECK *param); - void restore_vcos_after_repair(); public: ha_myisam(handlerton *hton, TABLE_SHARE *table_arg); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_34682.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_34682.result new file mode 100644 index 00000000000..7253e136488 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_34682.result @@ -0,0 +1,19 @@ +set @old_aria_encrypt_tables=@@global.aria_encrypt_tables; +set global aria_encrypt_tables=ON; +CREATE FUNCTION spider_direct_sql RETURNS INT SONAME 'ha_spider.so'; +call mtr.add_suppression(".*\\[ERROR\\] SPIDER plugin initialization failed at.* by 'Initialization of encryption failed for"); +call mtr.add_suppression(".*\\[ERROR\\] Plugin 'SPIDER' registration as a STORAGE ENGINE failed."); +INSTALL PLUGIN spider SONAME 'ha_spider.so'; +ERROR HY000: Can't initialize function 'spider'; Plugin initialization function failed. +SELECT spider_direct_sql ('SELECT * FROM s','a','srv "b"'); +ERROR HY000: Can't initialize function 'spider_direct_sql'; Plugin 'SPIDER' is not loaded +Warnings: +Note 1305 FUNCTION test.spider_flush_table_mon_cache does not exist +Warnings: +Note 1305 FUNCTION test.spider_copy_tables does not exist +Warnings: +Note 1305 FUNCTION test.spider_ping_table does not exist +Warnings: +Note 1305 FUNCTION test.spider_bg_direct_sql does not exist +Warnings: +Note 1305 SONAME ha_spider.so does not exist diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_34682.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_34682.test new file mode 100644 index 00000000000..d61f7db4330 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_34682.test @@ -0,0 +1,14 @@ +set @old_aria_encrypt_tables=@@global.aria_encrypt_tables; +set global aria_encrypt_tables=ON; + +CREATE FUNCTION spider_direct_sql RETURNS INT SONAME 'ha_spider.so'; +call mtr.add_suppression(".*\\[ERROR\\] SPIDER plugin initialization failed at.* by 'Initialization of encryption failed for"); +call mtr.add_suppression(".*\\[ERROR\\] Plugin 'SPIDER' registration as a STORAGE ENGINE failed."); +--error ER_CANT_INITIALIZE_UDF +INSTALL PLUGIN spider SONAME 'ha_spider.so'; +--error ER_CANT_INITIALIZE_UDF +SELECT spider_direct_sql ('SELECT * FROM s','a','srv "b"'); + +--disable_query_log +--source ../../include/clean_up_spider.inc +set global aria_encrypt_tables=@old_aria_encrypt_tables; diff --git a/storage/spider/mysql-test/spider/include/clean_up_spider.inc b/storage/spider/mysql-test/spider/include/clean_up_spider.inc index 249606ec774..5b016e731d9 100644 --- a/storage/spider/mysql-test/spider/include/clean_up_spider.inc +++ b/storage/spider/mysql-test/spider/include/clean_up_spider.inc @@ -1,8 +1,8 @@ -DROP FUNCTION spider_flush_table_mon_cache; -DROP FUNCTION spider_copy_tables; -DROP FUNCTION spider_ping_table; -DROP FUNCTION spider_bg_direct_sql; -DROP FUNCTION spider_direct_sql; +DROP FUNCTION IF EXISTS spider_flush_table_mon_cache; +DROP FUNCTION IF EXISTS spider_copy_tables; +DROP FUNCTION IF EXISTS spider_ping_table; +DROP FUNCTION IF EXISTS spider_bg_direct_sql; +DROP FUNCTION IF EXISTS spider_direct_sql; UNINSTALL SONAME IF EXISTS 'ha_spider'; DROP TABLE IF EXISTS mysql.spider_xa; DROP TABLE IF EXISTS mysql.spider_xa_member; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 0a4fa2bbdea..e101acdc684 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -6493,8 +6493,10 @@ bool spider_init_system_tables() /* - Spider is typically loaded before ddl_recovery, but DDL statements - cannot be executed before ddl_recovery, so we delay system table creation. + Spider may be loaded before ddl_recovery (e.g. with + --plugin-load-add), but DDL statements in spider init queries cannot + be executed before ddl_recovery, so we execute these queries only + after ddl recovery. */ static int spider_after_ddl_recovery(handlerton *) { @@ -6911,6 +6913,7 @@ error_pt_attr_setstate: */ pthread_attr_destroy(&spider_pt_attr); error_pt_attr_init: + spider_hton_ptr= NULL; DBUG_RETURN(error_num); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index c2f0406f3fc..df28696f2be 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -22062,6 +22062,452 @@ static void test_mdev_30159() myquery(rc); } + +#ifndef EMBEDDED_LIBRARY +/** + Test case for bulk UPDATE against a table with an active AFTER UPDATE + trigger. +*/ + +static void test_mdev_34718_au() +{ + int rc; + MYSQL_STMT *stmt_update; + MYSQL_BIND bind[2]; + unsigned int vals[]= { 1, 2, 3}; + unsigned int new_vals[]= { 5, 6, 7}; + unsigned int vals_array_len= 3; + my_ulonglong row_count; + MYSQL_RES *result; + MYSQL_ROW row; + const char *update_stmt= "UPDATE t1 SET a = ? WHERE a = ?"; + const char *update_stmt_state_info; + + myheader("test_mdev_34718_au"); + + /* Set up test's environment */ + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TRIGGER t1_au AFTER UPDATE ON t1 " + "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (NEW.a); END;"); + + stmt_update= mysql_stmt_init(mysql); + check_stmt(stmt_update); + + rc= mysql_stmt_prepare(stmt_update, update_stmt, strlen(update_stmt)); + check_execute(stmt_update, rc); + + memset(&bind[0], 0, sizeof(MYSQL_BIND)); + memset(&bind[1], 0, sizeof(MYSQL_BIND)); + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= new_vals; + + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= vals; + + /* + Every input positional parameter is bound with array of 3 elements + containing actual values for positional parameters + */ + rc= mysql_stmt_attr_set(stmt_update, STMT_ATTR_ARRAY_SIZE, &vals_array_len); + check_execute(stmt_update, rc); + + rc= mysql_stmt_bind_param(stmt_update, bind); + check_execute(stmt_update, rc); + + /* + Execution of this prepared statement replaces the table rows (1), (2), (3) + with values (5), (6), (7) + */ + rc= mysql_stmt_execute(stmt_update); + check_execute(stmt_update, rc); + + /* + Check that the BULK UPDATE statement affects exactly 3 rows + */ + row_count = mysql_stmt_affected_rows(stmt_update); + DIE_UNLESS(row_count == 3); + + update_stmt_state_info= mysql_info(mysql); + + /* + Check that information about executed operation is matched with + the expected result + */ + DIE_UNLESS(!strcmp("Rows matched: 3 Changed: 3 Warnings: 0", + update_stmt_state_info)); + + /* + * Check that the AFTER UPDATE trigger of the table t1 does work correctly + * and inserts the rows (5), (6), (7) into the table t2. + */ + rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 " + "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a"); + myquery(rc); + + result= mysql_store_result(mysql); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 5); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 6); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 7); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 5); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 6); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 7); + + row= mysql_fetch_row(result); + DIE_UNLESS(row == NULL); + + mysql_free_result(result); + + mysql_stmt_close(stmt_update); + + /* Clean up */ + rc= mysql_query(mysql, "DROP TABLE t1, t2"); + myquery(rc); +} + + +/** + Test case for bulk UPDATE against a table with an active BEFORE UPDATE + trigger. +*/ + +static void test_mdev_34718_bu() +{ + int rc; + MYSQL_STMT *stmt_update; + MYSQL_BIND bind[2]; + unsigned int vals[]= { 1, 2, 3}; + unsigned int new_vals[]= { 5, 6, 7}; + unsigned int vals_array_len= 3; + my_ulonglong row_count; + MYSQL_RES *result; + MYSQL_ROW row; + const char *update_stmt= "UPDATE t1 SET a = ? WHERE a = ?"; + const char *update_stmt_state_info; + + myheader("test_mdev_34718_bu"); + + /* Set up test's environment */ + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TRIGGER t1_au BEFORE UPDATE ON t1 " + "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (NEW.a); END;"); + + /* Initialize the prepared statement and set it up for bulk operations */ + stmt_update= mysql_stmt_init(mysql); + check_stmt(stmt_update); + + rc= mysql_stmt_prepare(stmt_update, update_stmt, strlen(update_stmt)); + check_execute(stmt_update, rc); + + memset(&bind[0], 0, sizeof(MYSQL_BIND)); + memset(&bind[1], 0, sizeof(MYSQL_BIND)); + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= new_vals; + + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= vals; + + /* + Every input positional parameter is bound with array of 3 elements + containing actual values for positional parameters + */ + rc= mysql_stmt_attr_set(stmt_update, STMT_ATTR_ARRAY_SIZE, &vals_array_len); + check_execute(stmt_update, rc); + + rc= mysql_stmt_bind_param(stmt_update, bind); + check_execute(stmt_update, rc); + + /* + Execution of this prepared statement replaces the table rows (1), (2), (3) + with values (5), (6), (7) + */ + rc= mysql_stmt_execute(stmt_update); + check_execute(stmt_update, rc); + + /* + Check that the BULK UPDATE statement affects exactly 3 rows + */ + row_count= mysql_stmt_affected_rows(stmt_update); + DIE_UNLESS(row_count == 3); + + update_stmt_state_info= mysql_info(mysql); + + /* + Check that information about executed operation is matched with + the expected result + */ + DIE_UNLESS(!strcmp("Rows matched: 3 Changed: 3 Warnings: 0", + update_stmt_state_info)); + + /* + * Check that the BEFORE UPDATE trigger of the table t1 does work correctly + * and inserts the rows (5), (6), (7) into the table t2. + */ + rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 " + "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a"); + myquery(rc); + + result= mysql_store_result(mysql); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 5); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 6); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 7); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 5); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 6); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 7); + + row= mysql_fetch_row(result); + DIE_UNLESS(row == NULL); + + mysql_free_result(result); + + mysql_stmt_close(stmt_update); + + /* Clean up */ + rc= mysql_query(mysql, "DROP TABLE t1, t2"); + myquery(rc); +} + + +/** + Test case for bulk DELETE against a table with an active BEFORE DELETE + trigger. +*/ + +static void test_mdev_34718_bd() +{ + int rc; + MYSQL_STMT *stmt_delete; + MYSQL_BIND bind[1]; + unsigned int vals[]= { 1, 2, 3}; + unsigned int vals_array_len= 3; + my_ulonglong row_count; + MYSQL_RES *result; + MYSQL_ROW row; + const char *delete_stmt= "DELETE FROM t1 WHERE a = ?"; + + myheader("test_mdev_34718_bd"); + + /* Set up test's environment */ + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TRIGGER t1_bd BEFORE DELETE ON t1 " + "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (OLD.a); END;"); + + /* Initialize the prepared statement and set it up for bulk operations */ + stmt_delete= mysql_stmt_init(mysql); + check_stmt(stmt_delete); + + rc= mysql_stmt_prepare(stmt_delete, delete_stmt, strlen(delete_stmt)); + check_execute(stmt_delete, rc); + + memset(&bind[0], 0, sizeof(MYSQL_BIND)); + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= vals; + + /* + Input positional parameter is bound with array of 3 elements + containing actual values for the positional parameter + */ + rc= mysql_stmt_attr_set(stmt_delete, STMT_ATTR_ARRAY_SIZE, &vals_array_len); + check_execute(stmt_delete, rc); + + rc= mysql_stmt_bind_param(stmt_delete, bind); + check_execute(stmt_delete, rc); + + /* + Execution of this prepared statement deletes the rows (1), (2), (3) + from the table t1 and inserts the rows (1), (2), (3) into the table t2 + in result of firing the BEFORE DELETE trigger + */ + rc= mysql_stmt_execute(stmt_delete); + check_execute(stmt_delete, rc); + + /* + Check that the BULK DELETE statement affects exactly 3 rows + */ + row_count= mysql_stmt_affected_rows(stmt_delete); + DIE_UNLESS(row_count == 3); + + /* + * Check that the BEFORE DELETE trigger of the table t1 does work correctly + * and inserts the rows (1), (2), (3) into the table t2. + */ + rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 " + "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a"); + myquery(rc); + + result= mysql_store_result(mysql); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3); + + row= mysql_fetch_row(result); + DIE_UNLESS(row == NULL); + + mysql_free_result(result); + + mysql_stmt_close(stmt_delete); + + /* Clean up */ + rc= mysql_query(mysql, "DROP TABLE t1, t2"); + myquery(rc); +} + + +/** + Test case for bulk DELETE against a table with an active AFTER DELETE + trigger. +*/ +static void test_mdev_34718_ad() +{ + int rc; + MYSQL_STMT *stmt_delete; + MYSQL_BIND bind[1]; + unsigned int vals[]= { 1, 2, 3}; + unsigned int vals_array_len= 3; + my_ulonglong row_count; + MYSQL_RES *result; + MYSQL_ROW row; + const char *delete_stmt= "DELETE FROM t1 WHERE a = ?"; + + myheader("test_mdev_34718_bd"); + + /* Set up test's environment */ + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TRIGGER t1_bd AFTER DELETE ON t1 " + "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (OLD.a); END;"); + + /* Initialize the prepared statement and set it up for bulk operations */ + stmt_delete= mysql_stmt_init(mysql); + check_stmt(stmt_delete); + + rc= mysql_stmt_prepare(stmt_delete, delete_stmt, strlen(delete_stmt)); + check_execute(stmt_delete, rc); + + memset(&bind[0], 0, sizeof(MYSQL_BIND)); + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= vals; + + /* + Input positional parameter is bound with array of 3 elements + containing actual values for the positional parameter + */ + rc= mysql_stmt_attr_set(stmt_delete, STMT_ATTR_ARRAY_SIZE, &vals_array_len); + check_execute(stmt_delete, rc); + + rc= mysql_stmt_bind_param(stmt_delete, bind); + check_execute(stmt_delete, rc); + + /* + Execution of this prepared statement deletes the rows (1), (2), (3) + from the table t1 and inserts the rows (1), (2), (3) into the table t2 + in result of firing the BEFORE DELETE trigger + */ + rc= mysql_stmt_execute(stmt_delete); + check_execute(stmt_delete, rc); + + /* + Check that the BULK DELETE statement affects exactly 3 rows + */ + row_count= mysql_stmt_affected_rows(stmt_delete); + DIE_UNLESS(row_count == 3); + + /* + * Check that the AFTER DELETE trigger of the table t1 does work correctly + * and inserts the rows (1), (2), (3) into the table t2. + */ + rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 " + "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a"); + myquery(rc); + + result= mysql_store_result(mysql); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2); + + row= mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3); + + row= mysql_fetch_row(result); + DIE_UNLESS(row == NULL); + + mysql_free_result(result); + + mysql_stmt_close(stmt_delete); + + /* Clean up */ + rc= mysql_query(mysql, "DROP TABLE t1, t2"); + myquery(rc); +} +#endif // EMBEDDED_LIBRARY + /* Check that server_status returned after connecting to server is consistent with the value of autocommit variable. @@ -22630,6 +23076,10 @@ static struct my_tests_st my_tests[]= { { "test_cache_metadata", test_cache_metadata}, #ifndef EMBEDDED_LIBRARY { "test_mdev_24411", test_mdev_24411}, + { "test_mdev_34718_bu", test_mdev_34718_bu }, + { "test_mdev_34718_au", test_mdev_34718_au }, + { "test_mdev_34718_bd", test_mdev_34718_bd }, + { "test_mdev_34718_ad", test_mdev_34718_ad }, #endif { "test_mdev_10075", test_mdev_10075}, { 0, 0 }