summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-10-21 15:26:25 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-10-21 15:26:25 +0300
commit5f8561a6bcdb66e05ca539365cce33a9fc1817a2 (patch)
tree3ceb20e3e0e8fc1a0759199ccdf7238f31fd4267
parent3c2ab896b9642c43805a5dfc174c81fc5f902db0 (diff)
parent489ef007bec398c3b7b628325b225c3a015922cf (diff)
downloadmariadb-git-5f8561a6bcdb66e05ca539365cce33a9fc1817a2.tar.gz
Merge 10.4 into 10.5
-rw-r--r--configure.cmake20
-rw-r--r--mysql-test/main/ctype_utf16le.result33
-rw-r--r--mysql-test/main/ctype_utf16le.test37
-rw-r--r--mysql-test/main/ctype_utf8.result17
-rw-r--r--mysql-test/main/ctype_utf8.test18
-rw-r--r--mysql-test/main/func_json.result6
-rw-r--r--mysql-test/main/func_json.test6
-rw-r--r--mysql-test/main/information_schema.result20
-rw-r--r--mysql-test/main/information_schema.test21
-rw-r--r--mysql-test/main/long_unique_innodb.opt1
-rw-r--r--mysql-test/main/long_unique_innodb.result3
-rw-r--r--mysql-test/main/long_unique_innodb.test5
-rw-r--r--mysql-test/main/mysql-metadata.result2
-rw-r--r--mysql-test/main/mysql_upgrade.result72
-rw-r--r--mysql-test/main/mysql_upgrade.test38
-rw-r--r--mysql-test/main/sp-code.result30
-rw-r--r--mysql-test/main/sp-code.test32
-rw-r--r--mysql-test/main/type_json.result4
-rw-r--r--mysql-test/main/view.result11
-rw-r--r--mysql-test/main/view.test19
-rw-r--r--mysql-test/main/xa.result15
-rw-r--r--mysql-test/main/xa.test17
-rw-r--r--mysql-test/suite/galera/r/galera_ftwrl_drain.result16
-rw-r--r--mysql-test/suite/galera/t/galera_ftwrl_drain.test11
-rw-r--r--mysql-test/suite/gcol/inc/gcol_column_def_options.inc11
-rw-r--r--mysql-test/suite/gcol/r/gcol_column_def_options_innodb.result6
-rw-r--r--mysql-test/suite/gcol/r/gcol_column_def_options_myisam.result6
-rw-r--r--mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff9
-rw-r--r--mysql-test/suite/innodb/r/default_row_format_create.result23
-rw-r--r--mysql-test/suite/innodb/r/update_time.result3
-rw-r--r--mysql-test/suite/innodb/t/default_row_format_create.test25
-rw-r--r--mysql-test/suite/innodb/t/update_time-master.opt2
-rw-r--r--mysql-test/suite/innodb/t/update_time.test14
-rw-r--r--mysql-test/suite/innodb_fts/r/basic.result2
-rw-r--r--mysql-test/suite/innodb_fts/r/bug_32831765.result131
-rw-r--r--mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result21
-rw-r--r--mysql-test/suite/innodb_fts/t/basic.test2
-rw-r--r--mysql-test/suite/innodb_fts/t/bug_32831765.test164
-rw-r--r--mysql-test/suite/innodb_fts/t/innodb_fts_misc_1.test18
-rw-r--r--mysql-test/suite/plugins/r/simple_password_check.result20
-rw-r--r--mysql-test/suite/plugins/t/simple_password_check.test14
-rw-r--r--mysql-test/suite/roles/rebuild_role_grants.result266
-rw-r--r--mysql-test/suite/roles/rebuild_role_grants.test31
-rw-r--r--mysql-test/suite/rpl/include/rpl_reset_slave_all_check.inc48
-rw-r--r--mysql-test/suite/rpl/r/rpl_change_master_find_log_pos_err.result43
-rw-r--r--mysql-test/suite/rpl/r/rpl_reset_slave_all_clears_filters.result54
-rw-r--r--mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test93
-rw-r--r--mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test72
-rw-r--r--mysys/CMakeLists.txt4
-rw-r--r--scripts/mysql_system_tables_fix.sql2
-rw-r--r--sql/item.cc44
-rw-r--r--sql/item_jsonfunc.cc1
-rw-r--r--sql/log.h14
-rw-r--r--sql/log_event_server.cc37
-rw-r--r--sql/rpl_mi.cc8
-rw-r--r--sql/rpl_mi.h5
-rw-r--r--sql/sql_acl.cc423
-rw-r--r--sql/sql_handler.cc3
-rw-r--r--sql/sql_repl.cc10
-rw-r--r--sql/sql_select.cc23
-rw-r--r--sql/sql_show.cc7
-rw-r--r--sql/sql_table.cc15
-rw-r--r--sql/table.cc15
-rw-r--r--storage/connect/valblk.cpp41
-rw-r--r--storage/connect/valblk.h50
-rw-r--r--storage/innobase/CMakeLists.txt6
-rw-r--r--storage/innobase/fts/fts0fts.cc24
-rw-r--r--storage/innobase/fts/fts0opt.cc13
-rw-r--r--storage/innobase/fts/fts0que.cc7
-rw-r--r--storage/innobase/handler/ha_innodb.cc36
-rw-r--r--storage/innobase/handler/handler0alter.cc2
-rw-r--r--storage/innobase/handler/i_s.cc18
-rw-r--r--storage/innobase/include/fts0fts.h4
-rw-r--r--storage/innobase/include/fts0types.h38
-rw-r--r--storage/innobase/include/fts0vlc.h124
-rw-r--r--storage/innobase/include/fts0vlc.ic142
-rw-r--r--storage/innobase/include/mach0data.h22
-rw-r--r--storage/innobase/include/ut0wqueue.h11
-rw-r--r--storage/innobase/row/row0mysql.cc17
-rw-r--r--storage/innobase/trx/trx0trx.cc18
-rw-r--r--storage/innobase/unittest/CMakeLists.txt22
-rw-r--r--storage/innobase/unittest/innodb_fts-t.cc52
-rw-r--r--storage/innobase/ut/ut0wqueue.cc24
-rw-r--r--storage/mroonga/vendor/groonga/lib/CMakeLists.txt5
84 files changed, 2226 insertions, 593 deletions
diff --git a/configure.cmake b/configure.cmake
index a78b83bd33c..c97240237e9 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -866,7 +866,25 @@ int main()
long long int *ptr= &var;
return (int)__atomic_load_n(ptr, __ATOMIC_SEQ_CST);
}"
-HAVE_GCC_C11_ATOMICS)
+HAVE_GCC_C11_ATOMICS_WITHOUT_LIBATOMIC)
+IF (HAVE_GCC_C11_ATOMICS_WITHOUT_LIBATOMIC)
+ SET(HAVE_GCC_C11_ATOMICS True)
+ELSE()
+ SET(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ LIST(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
+ CHECK_CXX_SOURCE_COMPILES("
+ int main()
+ {
+ long long int var= 1;
+ long long int *ptr= &var;
+ return (int)__atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+ }"
+ HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ IF(HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ SET(HAVE_GCC_C11_ATOMICS True)
+ ENDIF()
+ SET(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES})
+ENDIF()
IF(WITH_VALGRIND)
SET(HAVE_valgrind 1)
diff --git a/mysql-test/main/ctype_utf16le.result b/mysql-test/main/ctype_utf16le.result
index c43106aa042..aff755d95ae 100644
--- a/mysql-test/main/ctype_utf16le.result
+++ b/mysql-test/main/ctype_utf16le.result
@@ -3000,5 +3000,38 @@ DROP TABLE t1;
#
SET DEFAULT_STORAGE_ENGINE=Default;
#
+# MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+#
+SET NAMES utf8;
+SET SESSION character_set_connection= utf16le;
+CREATE TABLE kv (v TEXT CHARACTER SET latin1);
+CREATE TABLE t (a INT);
+CREATE VIEW v AS SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+LOAD DATA INFILE 'MYSQLD_DATADIR/test/v.frm' REPLACE INTO TABLE kv CHARACTER SET latin1;
+SELECT LOWER(v) FROM kv WHERE v LIKE _binary'query=%';
+LOWER(v)
+query=select `information_schema`.`tables`.`table_catalog` as `table_catalog`,`information_schema`.`tables`.`table_schema` as `table_schema`,`information_schema`.`tables`.`table_name` as `table_name`,`information_schema`.`tables`.`table_type` as `table_type`,`information_schema`.`tables`.`engine` as `engine`,`information_schema`.`tables`.`version` as `version`,`information_schema`.`tables`.`row_format` as `row_format`,`information_schema`.`tables`.`table_rows` as `table_rows`,`information_schema`.`tables`.`avg_row_length` as `avg_row_length`,`information_schema`.`tables`.`data_length` as `data_length`,`information_schema`.`tables`.`max_data_length` as `max_data_length`,`information_schema`.`tables`.`index_length` as `index_length`,`information_schema`.`tables`.`data_free` as `data_free`,`information_schema`.`tables`.`auto_increment` as `auto_increment`,`information_schema`.`tables`.`create_time` as `create_time`,`information_schema`.`tables`.`update_time` as `update_time`,`information_schema`.`tables`.`check_time` as `check_time`,`information_schema`.`tables`.`table_collation` as `table_collation`,`information_schema`.`tables`.`checksum` as `checksum`,`information_schema`.`tables`.`create_options` as `create_options`,`information_schema`.`tables`.`table_comment` as `table_comment`,`information_schema`.`tables`.`max_index_length` as `max_index_length`,`information_schema`.`tables`.`temporary` as `temporary` from `information_schema`.`tables` where `information_schema`.`tables`.`table_name` = 't1'
+TRUNCATE TABLE kv;
+SELECT * FROM v;
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY
+LOCK TABLE t WRITE;
+UNLOCK TABLES;
+DROP VIEW v;
+DROP TABLE t;
+DROP TABLE kv;
+CREATE TABLE t (a INT);
+SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=CONCAT('t',0x00,'1');
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY
+LOCK TABLE t WRITE;
+UNLOCK TABLES;
+DROP TABLE t;
+CREATE TABLE t (a INT);
+SELECT TABLE_NAME, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=CONCAT('t',0x00,'1');
+TABLE_NAME HEX(TABLE_NAME)
+SELECT TABLE_NAME, TABLE_SCHEMA, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=CONCAT('test',0x00,'1');
+TABLE_NAME TABLE_SCHEMA HEX(TABLE_NAME)
+DROP TABLE t;
+SET NAMES utf8;
+#
# End of 10.2 tests
#
diff --git a/mysql-test/main/ctype_utf16le.test b/mysql-test/main/ctype_utf16le.test
index 6f8fd71ec34..e3163d2f73e 100644
--- a/mysql-test/main/ctype_utf16le.test
+++ b/mysql-test/main/ctype_utf16le.test
@@ -3,6 +3,7 @@
-- source include/have_utf32.inc
-- source include/have_utf8mb4.inc
+let $MYSQLD_DATADIR= `select @@datadir`;
SET TIME_ZONE='+03:00';
@@ -811,5 +812,41 @@ let $coll_pad='utf16le_bin';
--source include/ctype_pad_all_engines.inc
--echo #
+--echo # MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+--echo #
+
+
+
+SET NAMES utf8;
+SET SESSION character_set_connection= utf16le;
+
+CREATE TABLE kv (v TEXT CHARACTER SET latin1);
+CREATE TABLE t (a INT);
+CREATE VIEW v AS SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA INFILE '$MYSQLD_DATADIR/test/v.frm' REPLACE INTO TABLE kv CHARACTER SET latin1;
+SELECT LOWER(v) FROM kv WHERE v LIKE _binary'query=%';
+TRUNCATE TABLE kv;
+SELECT * FROM v;
+LOCK TABLE t WRITE;
+UNLOCK TABLES;
+DROP VIEW v;
+DROP TABLE t;
+DROP TABLE kv;
+
+CREATE TABLE t (a INT);
+SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=CONCAT('t',0x00,'1');
+LOCK TABLE t WRITE;
+UNLOCK TABLES;
+DROP TABLE t;
+
+CREATE TABLE t (a INT);
+SELECT TABLE_NAME, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=CONCAT('t',0x00,'1');
+SELECT TABLE_NAME, TABLE_SCHEMA, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=CONCAT('test',0x00,'1');
+DROP TABLE t;
+
+SET NAMES utf8;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result
index 266292edab6..967cfdf8fbc 100644
--- a/mysql-test/main/ctype_utf8.result
+++ b/mysql-test/main/ctype_utf8.result
@@ -11244,6 +11244,23 @@ DROP TABLE t1;
#
SET DEFAULT_STORAGE_ENGINE=Default;
#
+# MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+#
+SET NAMES utf8;
+SET SESSION character_set_connection=latin1;
+CREATE VIEW v1 AS SELECT 'ä' AS c1;
+SELECT c1, HEX(c1) FROM v1;
+c1 HEX(c1)
+ä E4
+CREATE TABLE kv (v BLOB);
+LOAD DATA INFILE 'MYSQLD_DATADIR/test/v1.frm' REPLACE INTO TABLE kv;
+SELECT * FROM kv WHERE v LIKE _binary'query=%';
+v
+query=select 'ä' AS `c1`
+DROP TABLE kv;
+DROP VIEW v1;
+SET NAMES utf8;
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/main/ctype_utf8.test b/mysql-test/main/ctype_utf8.test
index 01e5a0e8c80..d01190b2049 100644
--- a/mysql-test/main/ctype_utf8.test
+++ b/mysql-test/main/ctype_utf8.test
@@ -2,6 +2,8 @@
# Tests with the utf8 character set
#
+let $MYSQLD_DATADIR= `select @@datadir`;
+
let collation=utf8_unicode_ci;
--source include/have_collation.inc
SET TIME_ZONE='+03:00';
@@ -2167,6 +2169,22 @@ let $coll_pad='utf8_bin';
--source include/ctype_pad_all_engines.inc
--echo #
+--echo # MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+--echo #
+
+SET NAMES utf8;
+SET SESSION character_set_connection=latin1;
+CREATE VIEW v1 AS SELECT 'ä' AS c1;
+SELECT c1, HEX(c1) FROM v1;
+CREATE TABLE kv (v BLOB);
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+eval LOAD DATA INFILE '$MYSQLD_DATADIR/test/v1.frm' REPLACE INTO TABLE kv;
+SELECT * FROM kv WHERE v LIKE _binary'query=%';
+DROP TABLE kv;
+DROP VIEW v1;
+SET NAMES utf8;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result
index 4ad7efea8af..74d301abf7a 100644
--- a/mysql-test/main/func_json.result
+++ b/mysql-test/main/func_json.result
@@ -934,6 +934,12 @@ CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DECIMAL) AS cd;
cf cd
0 0
#
+# MDEV-24585 Assertion `je->s.cs == nice_js->charset()' failed in json_nice.
+#
+SELECT JSON_REPLACE( JSON_DETAILED('["x"]'), '$.a', 'xx' );
+JSON_REPLACE( JSON_DETAILED('["x"]'), '$.a', 'xx' )
+["x"]
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test
index d598809adf5..668675551f6 100644
--- a/mysql-test/main/func_json.test
+++ b/mysql-test/main/func_json.test
@@ -552,6 +552,12 @@ SELECT
--echo #
+--echo # MDEV-24585 Assertion `je->s.cs == nice_js->charset()' failed in json_nice.
+--echo #
+
+SELECT JSON_REPLACE( JSON_DETAILED('["x"]'), '$.a', 'xx' );
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result
index 82f04e0aeb1..be209d1435c 100644
--- a/mysql-test/main/information_schema.result
+++ b/mysql-test/main/information_schema.result
@@ -2242,6 +2242,26 @@ SELECT * FROM v LIMIT ROWS EXAMINED 9;
ERROR HY000: Sort aborted:
DROP VIEW v;
#
+# MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+#
+CREATE TABLE t (a INT);
+SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=CONCAT('t',0x00,'1');
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY
+SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=CONCAT('test',0x00,'1');
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY
+DROP TABLE t;
+CREATE TABLE `a/~.b` (a INT);
+SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='a/~.b';
+TABLE_SCHEMA TABLE_NAME
+test a/~.b
+DROP TABLE `a/~.b`;
+CREATE DATABASE `a/~.b`;
+CREATE TABLE `a/~.b`.t1 (a INT);
+SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='a/~.b';
+TABLE_SCHEMA TABLE_NAME
+a/~.b t1
+DROP DATABASE `a/~.b`;
+#
# End of 10.2 Test
#
#
diff --git a/mysql-test/main/information_schema.test b/mysql-test/main/information_schema.test
index 17c029bc81f..284ecdfdf49 100644
--- a/mysql-test/main/information_schema.test
+++ b/mysql-test/main/information_schema.test
@@ -1949,6 +1949,27 @@ SELECT * FROM v LIMIT ROWS EXAMINED 9;
DROP VIEW v;
--echo #
+--echo # MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+--echo #
+
+# Expect empty sets if requested TABLE_NAME or TABLE_SCHEMA with zero bytes
+CREATE TABLE t (a INT);
+SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=CONCAT('t',0x00,'1');
+SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=CONCAT('test',0x00,'1');
+DROP TABLE t;
+
+# Make sure check_table_name() does not reject special characters
+CREATE TABLE `a/~.b` (a INT);
+SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='a/~.b';
+DROP TABLE `a/~.b`;
+
+# Make sure check_db_name() does not reject special characters
+CREATE DATABASE `a/~.b`;
+CREATE TABLE `a/~.b`.t1 (a INT);
+SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='a/~.b';
+DROP DATABASE `a/~.b`;
+
+--echo #
--echo # End of 10.2 Test
--echo #
diff --git a/mysql-test/main/long_unique_innodb.opt b/mysql-test/main/long_unique_innodb.opt
new file mode 100644
index 00000000000..058a129cdc2
--- /dev/null
+++ b/mysql-test/main/long_unique_innodb.opt
@@ -0,0 +1 @@
+--innodb-page-size=8K
diff --git a/mysql-test/main/long_unique_innodb.result b/mysql-test/main/long_unique_innodb.result
index 135bb0808cc..96e5fac7310 100644
--- a/mysql-test/main/long_unique_innodb.result
+++ b/mysql-test/main/long_unique_innodb.result
@@ -131,3 +131,6 @@ connection default;
drop table t1;
disconnect con1;
disconnect con2;
+# MDEV-20131 Assertion `!pk->has_virtual()' failed
+create table t1 (a text, primary key(a(1871))) engine=innodb;
+ERROR 42000: Specified key was too long; max key length is 1536 bytes
diff --git a/mysql-test/main/long_unique_innodb.test b/mysql-test/main/long_unique_innodb.test
index aac68cd2271..dd2d9f94de3 100644
--- a/mysql-test/main/long_unique_innodb.test
+++ b/mysql-test/main/long_unique_innodb.test
@@ -138,3 +138,8 @@ connection default;
drop table t1;
disconnect con1;
disconnect con2;
+
+--echo # MDEV-20131 Assertion `!pk->has_virtual()' failed
+
+--error ER_TOO_LONG_KEY
+create table t1 (a text, primary key(a(1871))) engine=innodb;
diff --git a/mysql-test/main/mysql-metadata.result b/mysql-test/main/mysql-metadata.result
index 51b3eb24f2b..1530465eaf8 100644
--- a/mysql-test/main/mysql-metadata.result
+++ b/mysql-test/main/mysql-metadata.result
@@ -79,7 +79,7 @@ Database: ``
Table: ``
Org_table: ``
Type: LONG_BLOB (format=json)
-Collation: binary (63)
+Collation: latin1_swedish_ci (8)
Length: 4294967295
Max_length: 0
Decimals: 0
diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result
index 6bb236b6fb8..2b74c22a078 100644
--- a/mysql-test/main/mysql_upgrade.result
+++ b/mysql-test/main/mysql_upgrade.result
@@ -842,6 +842,78 @@ count(*)
5
drop table mysql.global_priv;
rename table mysql.global_priv_bak to mysql.global_priv;
+#
+# Ensure that mysql_upgrade accounted for 0 password_last_changed
+# and doesn't PASSWORD EXPIRE a user account because < 10.4 zeroed it.
+#
+# switching from mysql.global_priv to mysql.user
+drop view mysql.user_bak;
+drop table mysql.user;
+truncate table mysql.tables_priv;
+FLUSH TABLES mysql.user;
+FLUSH PRIVILEGES;
+CREATE USER mariadb_102;
+UPDATE mysql.user SET password_last_changed=0 WHERE user='mariadb_102';
+FLUSH PRIVILEGES;
+Phase 1/7: Checking and upgrading mysql database
+Processing databases
+mysql
+mysql.column_stats OK
+mysql.columns_priv OK
+mysql.db OK
+mysql.event OK
+mysql.func OK
+mysql.global_priv_bak OK
+mysql.gtid_slave_pos OK
+mysql.help_category OK
+mysql.help_keyword OK
+mysql.help_relation OK
+mysql.help_topic OK
+mysql.index_stats OK
+mysql.innodb_index_stats OK
+mysql.innodb_table_stats OK
+mysql.plugin OK
+mysql.proc OK
+mysql.procs_priv OK
+mysql.proxies_priv OK
+mysql.roles_mapping OK
+mysql.servers OK
+mysql.table_stats OK
+mysql.tables_priv OK
+mysql.time_zone OK
+mysql.time_zone_leap_second OK
+mysql.time_zone_name OK
+mysql.time_zone_transition OK
+mysql.time_zone_transition_type OK
+mysql.transaction_registry OK
+mysql.user OK
+Upgrading from a version before MariaDB-10.1
+Phase 2/7: Installing used storage engines
+Checking for tables with unknown storage engine
+Phase 3/7: Fixing views
+Phase 4/7: Running 'mysql_fix_privilege_tables'
+Phase 5/7: Fixing table and database names
+Phase 6/7: Checking and upgrading tables
+Processing databases
+information_schema
+mtr
+mtr.global_suppressions OK
+mtr.test_suppressions OK
+performance_schema
+test
+Phase 7/7: Running 'FLUSH PRIVILEGES'
+OK
+SHOW CREATE USER mariadb_102;
+CREATE USER for mariadb_102@%
+CREATE USER `mariadb_102`@`%`
+connect con1,localhost,mariadb_102;
+select current_user();
+current_user()
+mariadb_102@%
+disconnect con1;
+connection default;
+drop table mysql.global_priv;
+rename table mysql.global_priv_bak to mysql.global_priv;
# End of 10.4 tests
#
# Check that mysql_upgrade can be run on mysqldump
diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test
index c40bf8b10be..54f47ae8657 100644
--- a/mysql-test/main/mysql_upgrade.test
+++ b/mysql-test/main/mysql_upgrade.test
@@ -356,6 +356,44 @@ select count(*) from mysql.global_priv;
drop table mysql.global_priv;
rename table mysql.global_priv_bak to mysql.global_priv;
+#
+# MDEV-26363 Former mysql-5.7 tables have password_last_changed to 0
+# on MariaDB updates, resulting in mysql_upgrade leaving them
+# with password expired.
+#
+
+--echo #
+--echo # Ensure that mysql_upgrade accounted for 0 password_last_changed
+--echo # and doesn't PASSWORD EXPIRE a user account because < 10.4 zeroed it.
+--echo #
+
+--source include/switch_to_mysql_user.inc
+drop view mysql.user_bak;
+drop table mysql.user;
+truncate table mysql.tables_priv;
+--copy_file std_data/mysql57user.frm $MYSQLD_DATADIR/mysql/user.frm
+--copy_file std_data/mysql57user.MYI $MYSQLD_DATADIR/mysql/user.MYI
+--copy_file std_data/mysql57user.MYD $MYSQLD_DATADIR/mysql/user.MYD
+FLUSH TABLES mysql.user;
+FLUSH PRIVILEGES;
+
+CREATE USER mariadb_102;
+# manually set the value like <10.4 previously did for testing mysql_upgrade.
+UPDATE mysql.user SET password_last_changed=0 WHERE user='mariadb_102';
+FLUSH PRIVILEGES;
+
+--exec $MYSQL_UPGRADE --force 2>&1
+# Should not have "PASSWORD EXPIRED"
+SHOW CREATE USER mariadb_102;
+connect con1,localhost,mariadb_102;
+select current_user();
+disconnect con1;
+connection default;
+
+drop table mysql.global_priv;
+rename table mysql.global_priv_bak to mysql.global_priv;
+--remove_file $MYSQLD_DATADIR/mysql_upgrade_info
+
--echo # End of 10.4 tests
#
diff --git a/mysql-test/main/sp-code.result b/mysql-test/main/sp-code.result
index f9cbdcce691..462c9f80263 100644
--- a/mysql-test/main/sp-code.result
+++ b/mysql-test/main/sp-code.result
@@ -972,6 +972,30 @@ DROP PROCEDURE testp_bug11763507;
DROP FUNCTION testf_bug11763507;
#END OF BUG#11763507 test.
#
+# MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+#
+SET NAMES utf8;
+SET SESSION character_set_connection=latin1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a VARCHAR(10) CHARACTER SET utf8;
+SET a='ä';
+SELECT a, 'ä' AS b;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set a@0 NULL
+1 set a@0 'ä'
+2 stmt 0 "SELECT a, 'ä' AS b"
+CALL p1;
+a b
+ä ä
+DROP PROCEDURE p1;
+#
+# End of 10.2 tests
+#
+#
# MDEV-13581 ROW TYPE OF t1 and t1%ROWTYPE for routine parameters
#
CREATE TABLE t1 (a INT, b TEXT);
@@ -1330,6 +1354,9 @@ Pos Instruction
5 hpop 1
drop function f1;
#
+# End of 10.3 tests
+#
+#
# MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
#
CREATE OR REPLACE PROCEDURE p1()
@@ -1344,3 +1371,6 @@ Pos Instruction
1 stmt 31 "SET GLOBAL max_error_count=60"
2 stmt 0 "SELECT @@GLOBAL.max_allowed_packet, @..."
DROP PROCEDURE p1;
+#
+# End of 10.5 tests
+#
diff --git a/mysql-test/main/sp-code.test b/mysql-test/main/sp-code.test
index 10bf1ba1322..eef3382f214 100644
--- a/mysql-test/main/sp-code.test
+++ b/mysql-test/main/sp-code.test
@@ -738,6 +738,30 @@ DROP FUNCTION testf_bug11763507;
--echo #
+--echo # MDEV-23408 Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset
+--echo #
+
+SET NAMES utf8;
+SET SESSION character_set_connection=latin1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a VARCHAR(10) CHARACTER SET utf8;
+ SET a='ä';
+ SELECT a, 'ä' AS b;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # End of 10.2 tests
+--echo #
+
+
+--echo #
--echo # MDEV-13581 ROW TYPE OF t1 and t1%ROWTYPE for routine parameters
--echo #
@@ -948,6 +972,10 @@ delimiter ;|
show function code f1;
drop function f1;
+--echo #
+--echo # End of 10.3 tests
+--echo #
+
--echo #
--echo # MDEV-19640 Wrong SHOW PROCEDURE output for SET GLOBAL sysvar1=expr, sysvar2=expr
@@ -963,3 +991,7 @@ $$
DELIMITER ;$$
SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1;
+
+--echo #
+--echo # End of 10.5 tests
+--echo #
diff --git a/mysql-test/main/type_json.result b/mysql-test/main/type_json.result
index 2c4f7b7d42b..dfe4699b361 100644
--- a/mysql-test/main/type_json.result
+++ b/mysql-test/main/type_json.result
@@ -121,8 +121,8 @@ js0 js1 js2 js3
SELECT js0, JSON_COMPACT(js0), JSON_COMPACT('{}') FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t1 t1 js0 js0 252 (format=json) 4294967295 0 Y 144 0 33
-def JSON_COMPACT(js0) 251 (format=json) 4294967295 0 Y 128 0 63
-def JSON_COMPACT('{}') 253 (format=json) 6 0 Y 128 0 63
+def JSON_COMPACT(js0) 251 (format=json) 4294967295 0 Y 128 0 33
+def JSON_COMPACT('{}') 253 (format=json) 6 0 Y 0 0 33
js0 JSON_COMPACT(js0) JSON_COMPACT('{}')
DROP TABLE t1;
#
diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result
index c9ef634e447..fa3afd93dfa 100644
--- a/mysql-test/main/view.result
+++ b/mysql-test/main/view.result
@@ -6835,6 +6835,17 @@ SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
drop view v1;
drop table t1;
#
+# MDEV-26299: Some views force server (and mysqldump) to generate
+# invalid SQL for their definitions
+#
+create view v1 as
+select * from
+(select
+"12345678901234567890123456789012345678901234567890123456789012345") as t1;
+drop view v1;
+CREATE VIEW v1 AS select `t1`.`12345678901234567890123456789012345678901234567890123456789012345` AS `Name_exp_1` from (select '12345678901234567890123456789012345678901234567890123456789012345') `t1`;
+drop view v1;
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test
index 4345abf1bd8..11476d5d49e 100644
--- a/mysql-test/main/view.test
+++ b/mysql-test/main/view.test
@@ -6549,6 +6549,25 @@ SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
drop view v1;
drop table t1;
+
+--echo #
+--echo # MDEV-26299: Some views force server (and mysqldump) to generate
+--echo # invalid SQL for their definitions
+--echo #
+
+create view v1 as
+ select * from
+ (select
+ "12345678901234567890123456789012345678901234567890123456789012345") as t1;
+
+let $definition=`select VIEW_DEFINITION from information_schema.views where TABLE_NAME="v1"`;
+
+drop view v1;
+
+eval CREATE VIEW v1 AS $definition;
+
+drop view v1;
+
--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/xa.result b/mysql-test/main/xa.result
index 50089bb1d5e..75f32a1a0aa 100644
--- a/mysql-test/main/xa.result
+++ b/mysql-test/main/xa.result
@@ -453,6 +453,21 @@ Message XAER_RMFAIL: The command cannot be executed when global transaction is i
xa commit 'foo';
drop table t1;
#
+# MDEV-22445 Crash on HANDLER READ NEXT after XA PREPARE
+#
+CREATE TABLE t (a INT KEY) ENGINE=InnoDB;
+HANDLER t OPEN AS t;
+XA START '0';
+SELECT * FROM t;
+a
+XA END '0';
+XA PREPARE '0';
+HANDLER t READ NEXT;
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
+# Cleanup
+XA COMMIT '0';
+DROP TABLE t;
+#
# End of 10.2 tests
#
XA BEGIN 'xid';
diff --git a/mysql-test/main/xa.test b/mysql-test/main/xa.test
index 499cbeaa88f..408c7e01c9d 100644
--- a/mysql-test/main/xa.test
+++ b/mysql-test/main/xa.test
@@ -597,6 +597,23 @@ xa commit 'foo';
drop table t1;
--echo #
+--echo # MDEV-22445 Crash on HANDLER READ NEXT after XA PREPARE
+--echo #
+
+CREATE TABLE t (a INT KEY) ENGINE=InnoDB;
+HANDLER t OPEN AS t;
+XA START '0';
+SELECT * FROM t;
+XA END '0';
+XA PREPARE '0';
+--error ER_XAER_RMFAIL
+HANDLER t READ NEXT;
+
+--echo # Cleanup
+XA COMMIT '0';
+DROP TABLE t;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/suite/galera/r/galera_ftwrl_drain.result b/mysql-test/suite/galera/r/galera_ftwrl_drain.result
index 2342643e745..aa1358a8bf7 100644
--- a/mysql-test/suite/galera/r/galera_ftwrl_drain.result
+++ b/mysql-test/suite/galera/r/galera_ftwrl_drain.result
@@ -10,9 +10,9 @@ connection node_2;
SET SESSION wsrep_sync_wait = 0;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
-SELECT COUNT(*) = 0 FROM t1;
-COUNT(*) = 0
-1
+SELECT COUNT(*) AS EXPECT_0 FROM t1;
+EXPECT_0
+0
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2a;
FLUSH TABLES WITH READ LOCK;;
@@ -29,12 +29,12 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
connection node_2a;
UNLOCK TABLES;
connection node_2;
-SELECT COUNT(*) = 1 FROM t1;
-COUNT(*) = 1
+SELECT COUNT(*) AS EXPECT_1 FROM t1;
+EXPECT_1
1
INSERT INTO t1 VALUES (3);
connection node_1;
-SELECT COUNT(*) = 2 FROM t1;
-COUNT(*) = 2
-1
+SELECT COUNT(*) AS EXPECT_2 FROM t1;
+EXPECT_2
+2
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_ftwrl_drain.test b/mysql-test/suite/galera/t/galera_ftwrl_drain.test
index c8cdda5d624..5f5555e6d42 100644
--- a/mysql-test/suite/galera/t/galera_ftwrl_drain.test
+++ b/mysql-test/suite/galera/t/galera_ftwrl_drain.test
@@ -18,7 +18,8 @@
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
--connection node_2
-
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'
+--source include/wait_condition.inc
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
@@ -31,7 +32,7 @@ SET SESSION wsrep_sync_wait = 0;
# Wait until applier has blocked
--source include/galera_wait_sync_point.inc
-SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) AS EXPECT_0 FROM t1;
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--connection node_2a
@@ -61,9 +62,11 @@ INSERT INTO t1 VALUES (2);
UNLOCK TABLES;
--connection node_2
-SELECT COUNT(*) = 1 FROM t1;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t1
+--source include/wait_condition.inc
+SELECT COUNT(*) AS EXPECT_1 FROM t1;
INSERT INTO t1 VALUES (3);
--connection node_1
-SELECT COUNT(*) = 2 FROM t1;
+SELECT COUNT(*) AS EXPECT_2 FROM t1;
DROP TABLE t1;
diff --git a/mysql-test/suite/gcol/inc/gcol_column_def_options.inc b/mysql-test/suite/gcol/inc/gcol_column_def_options.inc
index 6b4d60e15b0..31923f25f01 100644
--- a/mysql-test/suite/gcol/inc/gcol_column_def_options.inc
+++ b/mysql-test/suite/gcol/inc/gcol_column_def_options.inc
@@ -589,3 +589,14 @@ ALTER TABLE t1 ALTER COLUMN a SET DEFAULT 7,
--disable_info
DROP TABLE t1;
--enable_warnings
+
+--echo #
+--echo # MDEV-26262 frm is corrupted after ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
+--echo #
+
+--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
+CREATE TABLE MDEV_26262 (a INT,b INT AS (b) VIRTUAL);
+
+--let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err
+--let SEARCH_PATTERN=Incorrect information in file: './test/MDEV_26262.frm'
+--source include/search_pattern_in_file.inc
diff --git a/mysql-test/suite/gcol/r/gcol_column_def_options_innodb.result b/mysql-test/suite/gcol/r/gcol_column_def_options_innodb.result
index 8d12db6246b..8cf428cecd2 100644
--- a/mysql-test/suite/gcol/r/gcol_column_def_options_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_column_def_options_innodb.result
@@ -703,6 +703,12 @@ ADD COLUMN c INT AS (1 + DEFAULT(a)) VIRTUAL;
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
DROP TABLE t1;
+#
+# MDEV-26262 frm is corrupted after ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
+#
+CREATE TABLE MDEV_26262 (a INT,b INT AS (b) VIRTUAL);
+ERROR 01000: Expression for field `b` is referring to uninitialized field `b`
+NOT FOUND /Incorrect information in file: './test/MDEV_26262.frm'/ in mysqld.1.err
DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2,t3;
DROP PROCEDURE IF EXISTS p1;
diff --git a/mysql-test/suite/gcol/r/gcol_column_def_options_myisam.result b/mysql-test/suite/gcol/r/gcol_column_def_options_myisam.result
index 45bac8dce97..9f1ab38ae90 100644
--- a/mysql-test/suite/gcol/r/gcol_column_def_options_myisam.result
+++ b/mysql-test/suite/gcol/r/gcol_column_def_options_myisam.result
@@ -703,6 +703,12 @@ ADD COLUMN c INT AS (1 + DEFAULT(a)) VIRTUAL;
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
DROP TABLE t1;
+#
+# MDEV-26262 frm is corrupted after ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
+#
+CREATE TABLE MDEV_26262 (a INT,b INT AS (b) VIRTUAL);
+ERROR 01000: Expression for field `b` is referring to uninitialized field `b`
+NOT FOUND /Incorrect information in file: './test/MDEV_26262.frm'/ in mysqld.1.err
DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2,t3;
DROP PROCEDURE IF EXISTS p1;
diff --git a/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff b/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff
index fbf1d914f5b..2597d014636 100644
--- a/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff
+++ b/mysql-test/suite/innodb/r/default_row_format_create,redundant.rdiff
@@ -20,3 +20,12 @@
SET @save_format = @@GLOBAL.innodb_default_row_format;
SET GLOBAL innodb_default_row_format = redundant;
CREATE TABLE t1 (c1 INT) ENGINE=InnoDB;
+@@ -49,7 +49,7 @@
+ ERROR HY000: Can't create table `test`.`t` (errno: 140 "Wrong create options")
+ SHOW WARNINGS;
+ Level Code Message
+-Warning 1478 InnoDB: PAGE_COMPRESSED requires PAGE_COMPRESSION_LEVEL or innodb_compression_level > 0
++Warning 140 InnoDB: PAGE_COMPRESSED table can't have ROW_TYPE=REDUNDANT
+ Error 1005 Can't create table `test`.`t` (errno: 140 "Wrong create options")
+ Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB
+ CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1 page_compression_level=1;
diff --git a/mysql-test/suite/innodb/r/default_row_format_create.result b/mysql-test/suite/innodb/r/default_row_format_create.result
index 262e8bc7f19..50adc757b62 100644
--- a/mysql-test/suite/innodb/r/default_row_format_create.result
+++ b/mysql-test/suite/innodb/r/default_row_format_create.result
@@ -42,3 +42,26 @@ SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
t1 InnoDB # Redundant # # # # # # NULL # NULL NULL latin1_swedish_ci NULL 0 N
DROP TABLE t1;
+SET @save_level=@@GLOBAL.innodb_compression_level;
+SET GLOBAL innodb_compression_level=0;
+CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1;
+ERROR HY000: Can't create table `test`.`t` (errno: 140 "Wrong create options")
+SHOW WARNINGS;
+Level Code Message
+Warning 1478 InnoDB: PAGE_COMPRESSED requires PAGE_COMPRESSION_LEVEL or innodb_compression_level > 0
+Error 1005 Can't create table `test`.`t` (errno: 140 "Wrong create options")
+Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB
+CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1 page_compression_level=1;
+DROP TABLE IF EXISTS t;
+SET GLOBAL innodb_compression_level=1;
+CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1;
+DROP TABLE IF EXISTS t;
+SET GLOBAL innodb_compression_level=1;
+CREATE TABLE t(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC page_compressed=1;
+SET GLOBAL innodb_compression_level=0;
+ALTER TABLE t FORCE, ROW_FORMAT=DEFAULT, ALGORITHM=INPLACE;
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'PAGE_COMPRESSED'
+ALTER TABLE t FORCE, ROW_FORMAT=DEFAULT, ALGORITHM=COPY;
+ERROR HY000: Can't create table `test`.`t` (errno: 140 "Wrong create options")
+DROP TABLE t;
+SET GLOBAL innodb_compression_level=@save_level;
diff --git a/mysql-test/suite/innodb/r/update_time.result b/mysql-test/suite/innodb/r/update_time.result
index c2a842b7bfc..534914e0216 100644
--- a/mysql-test/suite/innodb/r/update_time.result
+++ b/mysql-test/suite/innodb/r/update_time.result
@@ -24,8 +24,7 @@ SELECT COUNT(*) FROM information_schema.innodb_buffer_page
WHERE table_name = '`test`.`t`';
COUNT(*)
1
-# INSERT lots of data in table 'big': begin
-# INSERT lots of data in table 'big': end
+INSERT INTO big SELECT REPEAT('a', 1024) FROM seq_1_to_10240;
SELECT COUNT(*) FROM information_schema.innodb_buffer_page
WHERE table_name = '`test`.`t`';
COUNT(*)
diff --git a/mysql-test/suite/innodb/t/default_row_format_create.test b/mysql-test/suite/innodb/t/default_row_format_create.test
index 03a7ebd3752..534a7312620 100644
--- a/mysql-test/suite/innodb/t/default_row_format_create.test
+++ b/mysql-test/suite/innodb/t/default_row_format_create.test
@@ -44,3 +44,28 @@ TRUNCATE TABLE t1;
--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 #
SHOW TABLE STATUS LIKE 't1';
DROP TABLE t1;
+
+SET @save_level=@@GLOBAL.innodb_compression_level;
+SET GLOBAL innodb_compression_level=0;
+--error ER_CANT_CREATE_TABLE
+CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1;
+SHOW WARNINGS;
+--disable_warnings
+--error 0,ER_CANT_CREATE_TABLE
+CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1 page_compression_level=1;
+DROP TABLE IF EXISTS t;
+SET GLOBAL innodb_compression_level=1;
+--error 0,ER_CANT_CREATE_TABLE
+CREATE TABLE t(c INT) ENGINE=InnoDB page_compressed=1;
+DROP TABLE IF EXISTS t;
+--enable_warnings
+
+SET GLOBAL innodb_compression_level=1;
+CREATE TABLE t(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC page_compressed=1;
+SET GLOBAL innodb_compression_level=0;
+--error ER_ILLEGAL_HA_CREATE_OPTION
+ALTER TABLE t FORCE, ROW_FORMAT=DEFAULT, ALGORITHM=INPLACE;
+--error ER_CANT_CREATE_TABLE
+ALTER TABLE t FORCE, ROW_FORMAT=DEFAULT, ALGORITHM=COPY;
+DROP TABLE t;
+SET GLOBAL innodb_compression_level=@save_level;
diff --git a/mysql-test/suite/innodb/t/update_time-master.opt b/mysql-test/suite/innodb/t/update_time-master.opt
index 9f283a9503f..f0fd647546d 100644
--- a/mysql-test/suite/innodb/t/update_time-master.opt
+++ b/mysql-test/suite/innodb/t/update_time-master.opt
@@ -1 +1 @@
---innodb-buffer-pool-size=10M
+--innodb-buffer-pool-size=5M
diff --git a/mysql-test/suite/innodb/t/update_time.test b/mysql-test/suite/innodb/t/update_time.test
index a95c5171e9b..fd1e082f5f2 100644
--- a/mysql-test/suite/innodb/t/update_time.test
+++ b/mysql-test/suite/innodb/t/update_time.test
@@ -10,6 +10,7 @@
-- source include/not_embedded.inc
# This test is slow on buildbot.
--source include/big_test.inc
+--source include/have_sequence.inc
CREATE TABLE t (a INT) ENGINE=INNODB;
@@ -33,18 +34,7 @@ SELECT COUNT(*) FROM information_schema.innodb_buffer_page
WHERE table_name = '`test`.`t`';
# evict table 't' by inserting as much data as the BP size itself
--- echo # INSERT lots of data in table 'big': begin
--- disable_query_log
-BEGIN;
--- let $i = 10240
-while ($i)
-{
- INSERT INTO big VALUES (REPEAT('a', 1024));
- dec $i;
-}
-COMMIT;
--- enable_query_log
--- echo # INSERT lots of data in table 'big': end
+INSERT INTO big SELECT REPEAT('a', 1024) FROM seq_1_to_10240;
# confirm that all pages for table 't' have been evicted
SELECT COUNT(*) FROM information_schema.innodb_buffer_page
diff --git a/mysql-test/suite/innodb_fts/r/basic.result b/mysql-test/suite/innodb_fts/r/basic.result
index b3fd94509c3..a98de60674a 100644
--- a/mysql-test/suite/innodb_fts/r/basic.result
+++ b/mysql-test/suite/innodb_fts/r/basic.result
@@ -313,9 +313,7 @@ FTS_DOC_ID
65536
131071
drop table t1;
-call mtr.add_suppression("\\[ERROR\\] InnoDB: Doc ID 20030101000000 is too big. Its difference with largest used Doc ID 0 cannot exceed or equal to 65535");
CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200), FULLTEXT(title)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL, NULL), (20030101000000, 20030102000000);
-ERROR HY000: Invalid InnoDB FTS Doc ID
DROP TABLE t1;
diff --git a/mysql-test/suite/innodb_fts/r/bug_32831765.result b/mysql-test/suite/innodb_fts/r/bug_32831765.result
new file mode 100644
index 00000000000..1b828f4266b
--- /dev/null
+++ b/mysql-test/suite/innodb_fts/r/bug_32831765.result
@@ -0,0 +1,131 @@
+#
+# Bug#32831765 SERVER HITS OOM CONDITION WHEN LOADING TWO
+# INNODB TABLES WITH FTS INDEXES
+#
+create table t1 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+create table t2 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+create table t3 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+create table t4 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+#create procedure to inset into the table.
+CREATE PROCEDURE `proc_insert`(IN tab_name VARCHAR(40))
+BEGIN
+DECLARE i INT DEFAULT 1;
+SET @insert_tbl =CONCAT('INSERT INTO ', tab_name, '( `col01`, `col02`,
+ `col03`, `col04`, `col05`, `col06`, `col07`, `col08`, `col09`, `col10`,
+ `col11`, `col12`, `col13`, `col14`, `col15`, `col16`, `col17`, `col18`,
+ `col19`, `col20`, `col21`, `col22`, `col23`, `col24`, `col25`, `col26`,
+ `col27`, `col28`, `col29`, `col30`)
+ VALUES ( MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()))');
+PREPARE ins_stmt FROM @insert_tbl;
+while (i <= 2000) DO
+EXECUTE ins_stmt;
+SET i = i + 1;
+END WHILE;
+DEALLOCATE PREPARE ins_stmt;
+END |
+SET @save_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,fts_optimize_wq_count_check";
+connect con1,localhost,root,,;
+call proc_insert('t1');
+connect con2,localhost,root,,;
+call proc_insert('t1');
+connect con3,localhost,root,,;
+call proc_insert('t2');
+connect con4,localhost,root,,;
+call proc_insert('t2');
+connect con5,localhost,root,,;
+call proc_insert('t3');
+connect con6,localhost,root,,;
+call proc_insert('t3');
+connect con7,localhost,root,,;
+call proc_insert('t4');
+connection default;
+call proc_insert('t4');
+SET GLOBAL debug_dbug= @save_dbug;
+connection con1;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection con4;
+disconnect con4;
+connection con5;
+disconnect con5;
+connection con6;
+disconnect con6;
+connection con7;
+disconnect con7;
+connection default;
+DROP TABLE t1,t2,t3,t4;
+DROP PROCEDURE proc_insert;
diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result
index 2e22e2e5a2f..38cf6c81617 100644
--- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result
+++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result
@@ -972,3 +972,24 @@ SELECT * FROM information_schema.innodb_ft_deleted;
DOC_ID
DROP TABLE t1;
SET GLOBAL innodb_ft_aux_table=DEFAULT;
+#
+# MDEV-19522 InnoDB commit fails when FTS_DOC_ID value
+# is greater than 4294967295
+#
+CREATE TABLE t1(
+FTS_DOC_ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+f1 TEXT, f2 TEXT, PRIMARY KEY (FTS_DOC_ID),
+FULLTEXT KEY (f1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,'txt','bbb');
+UPDATE t1 SET FTS_DOC_ID = 4294967298;
+SELECT * FROM t1 WHERE match(f1) against("txt");
+FTS_DOC_ID f1 f2
+4294967298 txt bbb
+SET @@session.insert_id = 100000000000;
+INSERT INTO t1(f1, f2) VALUES ('aaa', 'bbb');
+CREATE FULLTEXT INDEX i ON t1 (f2);
+SELECT * FROM t1 WHERE match(f2) against("bbb");
+FTS_DOC_ID f1 f2
+4294967298 txt bbb
+100000000000 aaa bbb
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb_fts/t/basic.test b/mysql-test/suite/innodb_fts/t/basic.test
index 7a5c83ffb06..53ad978a5b1 100644
--- a/mysql-test/suite/innodb_fts/t/basic.test
+++ b/mysql-test/suite/innodb_fts/t/basic.test
@@ -277,9 +277,7 @@ insert into t1(f1, f2) values(3, "This is the third record");
select FTS_DOC_ID from t1;
drop table t1;
-call mtr.add_suppression("\\[ERROR\\] InnoDB: Doc ID 20030101000000 is too big. Its difference with largest used Doc ID 0 cannot exceed or equal to 65535");
CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200), FULLTEXT(title)) ENGINE=InnoDB;
---error 182
INSERT INTO t1 VALUES (NULL, NULL), (20030101000000, 20030102000000);
DROP TABLE t1;
diff --git a/mysql-test/suite/innodb_fts/t/bug_32831765.test b/mysql-test/suite/innodb_fts/t/bug_32831765.test
new file mode 100644
index 00000000000..a4551cf91ef
--- /dev/null
+++ b/mysql-test/suite/innodb_fts/t/bug_32831765.test
@@ -0,0 +1,164 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--echo #
+--echo # Bug#32831765 SERVER HITS OOM CONDITION WHEN LOADING TWO
+--echo # INNODB TABLES WITH FTS INDEXES
+--echo #
+
+create table t1 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+
+create table t2 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+
+
+create table t3 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+
+create table t4 ( `id` int unsigned NOT NULL AUTO_INCREMENT, `col01` text,
+`col02` text, `col03` text, `col04` text, `col05` text, `col06` text, `col07`
+text, `col08` text, `col09` text, `col10` text, `col11` text, `col12` text,
+`col13` text, `col14` text, `col15` text, `col16` text, `col17` text, `col18`
+text, `col19` text, `col20` text, `col21` text, `col22` text, `col23` text,
+`col24` text, `col25` text, `col26` text, `col27` text, `col28` text, `col29`
+text, `col30` text, PRIMARY KEY (`id`), FULLTEXT KEY (`col01`), FULLTEXT KEY
+(`col02`), FULLTEXT KEY (`col03`), FULLTEXT KEY (`col04`), FULLTEXT KEY
+(`col05`), FULLTEXT KEY (`col06`), FULLTEXT KEY (`col07`), FULLTEXT KEY
+(`col08`), FULLTEXT KEY (`col09`), FULLTEXT KEY (`col10`), FULLTEXT KEY
+(`col11`), FULLTEXT KEY (`col12`), FULLTEXT KEY (`col13`), FULLTEXT KEY
+(`col14`), FULLTEXT KEY (`col15`), FULLTEXT KEY (`col16`), FULLTEXT KEY
+(`col17`), FULLTEXT KEY (`col18`), FULLTEXT KEY (`col19`), FULLTEXT KEY
+(`col20`), FULLTEXT KEY (`col21`), FULLTEXT KEY (`col22`), FULLTEXT KEY
+(`col23`), FULLTEXT KEY (`col24`), FULLTEXT KEY (`col25`), FULLTEXT KEY
+(`col26`), FULLTEXT KEY (`col27`), FULLTEXT KEY (`col28`), FULLTEXT KEY
+(`col29`), FULLTEXT KEY (`col30`)) engine=innodb;
+
+delimiter |;
+
+--echo #create procedure to inset into the table.
+CREATE PROCEDURE `proc_insert`(IN tab_name VARCHAR(40))
+BEGIN
+ DECLARE i INT DEFAULT 1;
+ SET @insert_tbl =CONCAT('INSERT INTO ', tab_name, '( `col01`, `col02`,
+ `col03`, `col04`, `col05`, `col06`, `col07`, `col08`, `col09`, `col10`,
+ `col11`, `col12`, `col13`, `col14`, `col15`, `col16`, `col17`, `col18`,
+ `col19`, `col20`, `col21`, `col22`, `col23`, `col24`, `col25`, `col26`,
+ `col27`, `col28`, `col29`, `col30`)
+ VALUES ( MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()), MD5(RAND()),
+ MD5(RAND()))');
+ PREPARE ins_stmt FROM @insert_tbl;
+ while (i <= 2000) DO
+ EXECUTE ins_stmt;
+ SET i = i + 1;
+ END WHILE;
+ DEALLOCATE PREPARE ins_stmt;
+END |
+
+delimiter ;|
+
+# Ensure that the number of SYNC requests will not exceed 1000.
+SET @save_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,fts_optimize_wq_count_check";
+
+connect (con1,localhost,root,,);
+send call proc_insert('t1');
+connect (con2,localhost,root,,);
+send call proc_insert('t1');
+connect (con3,localhost,root,,);
+send call proc_insert('t2');
+connect (con4,localhost,root,,);
+send call proc_insert('t2');
+connect (con5,localhost,root,,);
+send call proc_insert('t3');
+connect (con6,localhost,root,,);
+send call proc_insert('t3');
+connect (con7,localhost,root,,);
+send call proc_insert('t4');
+
+connection default;
+call proc_insert('t4');
+SET GLOBAL debug_dbug= @save_dbug;
+
+connection con1;
+reap;
+disconnect con1;
+
+connection con2;
+reap;
+disconnect con2;
+
+connection con3;
+reap;
+disconnect con3;
+
+connection con4;
+reap;
+disconnect con4;
+
+connection con5;
+reap;
+disconnect con5;
+
+connection con6;
+reap;
+disconnect con6;
+
+connection con7;
+reap;
+disconnect con7;
+
+connection default;
+DROP TABLE t1,t2,t3,t4;
+DROP PROCEDURE proc_insert;
diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_misc_1.test b/mysql-test/suite/innodb_fts/t/innodb_fts_misc_1.test
index adc10886d66..b0bf2c669ad 100644
--- a/mysql-test/suite/innodb_fts/t/innodb_fts_misc_1.test
+++ b/mysql-test/suite/innodb_fts/t/innodb_fts_misc_1.test
@@ -942,3 +942,21 @@ SET GLOBAL innodb_ft_aux_table='test/t1';
SELECT * FROM information_schema.innodb_ft_deleted;
DROP TABLE t1;
SET GLOBAL innodb_ft_aux_table=DEFAULT;
+
+--echo #
+--echo # MDEV-19522 InnoDB commit fails when FTS_DOC_ID value
+--echo # is greater than 4294967295
+--echo #
+CREATE TABLE t1(
+ FTS_DOC_ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ f1 TEXT, f2 TEXT, PRIMARY KEY (FTS_DOC_ID),
+ FULLTEXT KEY (f1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,'txt','bbb');
+UPDATE t1 SET FTS_DOC_ID = 4294967298;
+SELECT * FROM t1 WHERE match(f1) against("txt");
+SET @@session.insert_id = 100000000000;
+INSERT INTO t1(f1, f2) VALUES ('aaa', 'bbb');
+CREATE FULLTEXT INDEX i ON t1 (f2);
+SELECT * FROM t1 WHERE match(f2) against("bbb");
+# Cleanup
+DROP TABLE t1;
diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result
index f8f56bc8b15..b3712ee22d2 100644
--- a/mysql-test/suite/plugins/r/simple_password_check.result
+++ b/mysql-test/suite/plugins/r/simple_password_check.result
@@ -165,3 +165,23 @@ flush privileges;
uninstall plugin simple_password_check;
create user foo1 identified by 'pwd';
drop user foo1;
+#
+# MDEV-26650: Failed ALTER USER/GRANT statement removes the
+# password from the cache
+#
+create user foo1@localhost identified by '<GDFH:3ghj';
+show grants for foo1@localhost;
+Grants for foo1@localhost
+GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D'
+install soname "simple_password_check";
+ALTER USER foo1@localhost identified by 'foo1';
+ERROR HY000: Operation ALTER USER failed for 'foo1'@'localhost'
+show grants for foo1@localhost;
+Grants for foo1@localhost
+GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D'
+flush privileges;
+show grants for foo1@localhost;
+Grants for foo1@localhost
+GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D'
+drop user foo1@localhost;
+uninstall plugin simple_password_check;
diff --git a/mysql-test/suite/plugins/t/simple_password_check.test b/mysql-test/suite/plugins/t/simple_password_check.test
index b7d631ab4bb..dfb078df638 100644
--- a/mysql-test/suite/plugins/t/simple_password_check.test
+++ b/mysql-test/suite/plugins/t/simple_password_check.test
@@ -122,3 +122,17 @@ uninstall plugin simple_password_check;
create user foo1 identified by 'pwd';
drop user foo1;
+--echo #
+--echo # MDEV-26650: Failed ALTER USER/GRANT statement removes the
+--echo # password from the cache
+--echo #
+create user foo1@localhost identified by '<GDFH:3ghj';
+show grants for foo1@localhost;
+install soname "simple_password_check";
+--error ER_CANNOT_USER
+ALTER USER foo1@localhost identified by 'foo1';
+show grants for foo1@localhost;
+flush privileges;
+show grants for foo1@localhost;
+drop user foo1@localhost;
+uninstall plugin simple_password_check;
diff --git a/mysql-test/suite/roles/rebuild_role_grants.result b/mysql-test/suite/roles/rebuild_role_grants.result
index f8297d91024..b8d747537aa 100644
--- a/mysql-test/suite/roles/rebuild_role_grants.result
+++ b/mysql-test/suite/roles/rebuild_role_grants.result
@@ -65,3 +65,269 @@ drop role look, isp, xxx, ppp;
connection default;
disconnect con1;
drop user nnnn@'%';
+CREATE USER u@localhost;
+CREATE ROLE r1;
+CREATE ROLE r2;
+CREATE ROLE r3;
+CREATE ROLE r4;
+CREATE ROLE r5;
+CREATE ROLE r6;
+CREATE ROLE r7;
+CREATE ROLE r8;
+CREATE ROLE r9;
+CREATE ROLE r10;
+CREATE ROLE r11;
+CREATE ROLE r12;
+CREATE ROLE r13;
+CREATE ROLE r14;
+CREATE ROLE r15;
+CREATE ROLE r16;
+CREATE ROLE r17;
+CREATE ROLE r18;
+CREATE ROLE r19;
+CREATE ROLE r20;
+CREATE ROLE r21;
+CREATE ROLE r22;
+CREATE ROLE r23;
+CREATE ROLE r24;
+CREATE ROLE r25;
+CREATE ROLE r26;
+CREATE ROLE r27;
+CREATE ROLE r28;
+CREATE ROLE r29;
+CREATE ROLE r30;
+CREATE ROLE r31;
+CREATE ROLE r32;
+CREATE ROLE r33;
+CREATE ROLE r34;
+CREATE ROLE r35;
+CREATE ROLE r36;
+CREATE ROLE r37;
+CREATE ROLE r38;
+CREATE ROLE r39;
+CREATE ROLE r40;
+CREATE ROLE r41;
+CREATE ROLE r42;
+CREATE ROLE r43;
+CREATE ROLE r44;
+CREATE ROLE r45;
+CREATE ROLE r46;
+CREATE ROLE r47;
+CREATE ROLE r48;
+CREATE ROLE r49;
+CREATE ROLE r50;
+CREATE ROLE r51;
+CREATE ROLE r52;
+CREATE ROLE r53;
+CREATE ROLE r54;
+CREATE ROLE r55;
+CREATE ROLE r56;
+CREATE ROLE r57;
+CREATE ROLE r58;
+CREATE ROLE r59;
+CREATE ROLE r60;
+CREATE ROLE r61;
+CREATE ROLE r62;
+CREATE ROLE r63;
+CREATE ROLE r64;
+CREATE ROLE r65;
+CREATE ROLE r66;
+CREATE ROLE r67;
+CREATE ROLE r68;
+CREATE ROLE r69;
+CREATE ROLE r70;
+CREATE ROLE r71;
+CREATE ROLE r72;
+CREATE ROLE r73;
+CREATE ROLE r74;
+CREATE ROLE r75;
+CREATE ROLE r76;
+CREATE ROLE r77;
+CREATE ROLE r78;
+CREATE ROLE r79;
+CREATE ROLE r80;
+CREATE ROLE r81;
+CREATE ROLE r82;
+CREATE ROLE r83;
+CREATE ROLE r84;
+CREATE ROLE r85;
+CREATE ROLE r86;
+CREATE ROLE r87;
+CREATE ROLE r88;
+CREATE ROLE r89;
+CREATE ROLE r90;
+CREATE ROLE r91;
+CREATE ROLE r92;
+CREATE ROLE r93;
+CREATE ROLE r94;
+CREATE ROLE r95;
+CREATE ROLE r96;
+CREATE ROLE r97;
+CREATE ROLE r98;
+CREATE ROLE r99;
+CREATE ROLE r100;
+CREATE ROLE r101;
+CREATE ROLE r102;
+CREATE ROLE r103;
+CREATE ROLE r104;
+CREATE ROLE r105;
+CREATE ROLE r106;
+CREATE ROLE r107;
+CREATE ROLE r108;
+CREATE ROLE r109;
+CREATE ROLE r110;
+CREATE ROLE r111;
+CREATE ROLE r112;
+CREATE ROLE r113;
+CREATE ROLE r114;
+CREATE ROLE r115;
+CREATE ROLE r116;
+CREATE ROLE r117;
+CREATE ROLE r118;
+CREATE ROLE r119;
+CREATE ROLE r120;
+CREATE ROLE r121;
+CREATE ROLE r122;
+CREATE ROLE r123;
+CREATE ROLE r124;
+CREATE ROLE r125;
+CREATE ROLE r126;
+CREATE ROLE r127;
+CREATE ROLE r128;
+CREATE ROLE n;
+CREATE ROLE d WITH ADMIN n;
+CREATE ROLE '%' WITH ADMIN u@localhost;
+DROP ROLE n;
+CREATE USER 't';
+DROP ROLE r1;
+DROP ROLE r2;
+DROP ROLE r3;
+DROP ROLE r4;
+DROP ROLE r5;
+DROP ROLE r6;
+DROP ROLE r7;
+DROP ROLE r8;
+DROP ROLE r9;
+DROP ROLE r10;
+DROP ROLE r11;
+DROP ROLE r12;
+DROP ROLE r13;
+DROP ROLE r14;
+DROP ROLE r15;
+DROP ROLE r16;
+DROP ROLE r17;
+DROP ROLE r18;
+DROP ROLE r19;
+DROP ROLE r20;
+DROP ROLE r21;
+DROP ROLE r22;
+DROP ROLE r23;
+DROP ROLE r24;
+DROP ROLE r25;
+DROP ROLE r26;
+DROP ROLE r27;
+DROP ROLE r28;
+DROP ROLE r29;
+DROP ROLE r30;
+DROP ROLE r31;
+DROP ROLE r32;
+DROP ROLE r33;
+DROP ROLE r34;
+DROP ROLE r35;
+DROP ROLE r36;
+DROP ROLE r37;
+DROP ROLE r38;
+DROP ROLE r39;
+DROP ROLE r40;
+DROP ROLE r41;
+DROP ROLE r42;
+DROP ROLE r43;
+DROP ROLE r44;
+DROP ROLE r45;
+DROP ROLE r46;
+DROP ROLE r47;
+DROP ROLE r48;
+DROP ROLE r49;
+DROP ROLE r50;
+DROP ROLE r51;
+DROP ROLE r52;
+DROP ROLE r53;
+DROP ROLE r54;
+DROP ROLE r55;
+DROP ROLE r56;
+DROP ROLE r57;
+DROP ROLE r58;
+DROP ROLE r59;
+DROP ROLE r60;
+DROP ROLE r61;
+DROP ROLE r62;
+DROP ROLE r63;
+DROP ROLE r64;
+DROP ROLE r65;
+DROP ROLE r66;
+DROP ROLE r67;
+DROP ROLE r68;
+DROP ROLE r69;
+DROP ROLE r70;
+DROP ROLE r71;
+DROP ROLE r72;
+DROP ROLE r73;
+DROP ROLE r74;
+DROP ROLE r75;
+DROP ROLE r76;
+DROP ROLE r77;
+DROP ROLE r78;
+DROP ROLE r79;
+DROP ROLE r80;
+DROP ROLE r81;
+DROP ROLE r82;
+DROP ROLE r83;
+DROP ROLE r84;
+DROP ROLE r85;
+DROP ROLE r86;
+DROP ROLE r87;
+DROP ROLE r88;
+DROP ROLE r89;
+DROP ROLE r90;
+DROP ROLE r91;
+DROP ROLE r92;
+DROP ROLE r93;
+DROP ROLE r94;
+DROP ROLE r95;
+DROP ROLE r96;
+DROP ROLE r97;
+DROP ROLE r98;
+DROP ROLE r99;
+DROP ROLE r100;
+DROP ROLE r101;
+DROP ROLE r102;
+DROP ROLE r103;
+DROP ROLE r104;
+DROP ROLE r105;
+DROP ROLE r106;
+DROP ROLE r107;
+DROP ROLE r108;
+DROP ROLE r109;
+DROP ROLE r110;
+DROP ROLE r111;
+DROP ROLE r112;
+DROP ROLE r113;
+DROP ROLE r114;
+DROP ROLE r115;
+DROP ROLE r116;
+DROP ROLE r117;
+DROP ROLE r118;
+DROP ROLE r119;
+DROP ROLE r120;
+DROP ROLE r121;
+DROP ROLE r122;
+DROP ROLE r123;
+DROP ROLE r124;
+DROP ROLE r125;
+DROP ROLE r126;
+DROP ROLE r127;
+DROP ROLE r128;
+DROP ROLE d;
+DROP ROLE '%';
+DROP USER 't';
+DROP USER u@localhost;
diff --git a/mysql-test/suite/roles/rebuild_role_grants.test b/mysql-test/suite/roles/rebuild_role_grants.test
index 84dbdf78fb8..7007df0ecdd 100644
--- a/mysql-test/suite/roles/rebuild_role_grants.test
+++ b/mysql-test/suite/roles/rebuild_role_grants.test
@@ -67,3 +67,34 @@ drop role look, isp, xxx, ppp;
connection default;
disconnect con1;
drop user nnnn@'%';
+
+#
+# MDEV-17964 Assertion `status == 0' failed in add_role_user_mapping_action
+# upon CREATE USER and DROP ROLE
+#
+CREATE USER u@localhost;
+
+--let $n= 1
+while ($n < 129)
+{
+ eval CREATE ROLE r$n;
+ inc $n;
+}
+
+CREATE ROLE n;
+CREATE ROLE d WITH ADMIN n;
+CREATE ROLE '%' WITH ADMIN u@localhost;
+DROP ROLE n;
+CREATE USER 't';
+
+--let $n= 1
+while ($n < 129)
+{
+ eval DROP ROLE r$n;
+ inc $n;
+}
+
+DROP ROLE d;
+DROP ROLE '%';
+DROP USER 't';
+DROP USER u@localhost;
diff --git a/mysql-test/suite/rpl/include/rpl_reset_slave_all_check.inc b/mysql-test/suite/rpl/include/rpl_reset_slave_all_check.inc
new file mode 100644
index 00000000000..adbaf32ebd7
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_reset_slave_all_check.inc
@@ -0,0 +1,48 @@
+# This file ensures that a slave's id filtering variables (i.e. DO_DOMAIN_IDS,
+# IGNORE_DOMAIN_IDS, and IGNORE_SERVER_IDS) are cleared after issuing
+# `RESET SLAVE ALL`.
+#
+# param $_do_domain_ids Integer list of values to use for DO_DOMAIN_IDS
+# param $_ignore_domain_ids Integer list of values to use for IGNORE_DOMAIN_IDS
+# param $_ignore_server_ids Integer list of values to use for IGNORE_SERVER_IDS
+#
+
+--echo # Id filtering variable values should be empty initially
+let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+let $ignore_server_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+
+if (`SELECT "$do_domain_ids_before" != "" OR
+ "$ignore_domain_ids_before" != "" OR
+ "$ignore_server_ids_before" != ""`)
+{
+ die("CHANGE MASTER TO id filter variables are not empty initially");
+}
+
+
+--echo # Set id filtering variables
+eval CHANGE MASTER TO DO_DOMAIN_IDS=$_do_domain_ids, IGNORE_DOMAIN_IDS=$_ignore_domain_ids, IGNORE_SERVER_IDS=$_ignore_server_ids, MASTER_USE_GTID=SLAVE_POS;
+let $do_domain_ids_set= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_set= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+let $ignore_server_ids_set= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+--echo # do domain id list: $do_domain_ids_set
+--echo # ignore domain id list: $ignore_domain_ids_set
+--echo # ignore server id list: $ignore_server_ids_set
+
+
+--echo # RESET SLAVE ALL should clear values for all id filtering variables
+RESET SLAVE ALL;
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+--source include/start_slave.inc
+--source include/stop_slave.inc
+
+let $do_domain_ids_cleared= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1);
+let $ignore_domain_ids_cleared= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1);
+let $ignore_server_ids_cleared= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1);
+if (`SELECT "$do_domain_ids_cleared" != "" OR
+ "$ignore_domain_ids_cleared" != "" OR
+ "$ignore_server_ids_cleared" != ""`)
+{
+ die("RESET SLAVE ALL did not clear id filtering variables");
+}
diff --git a/mysql-test/suite/rpl/r/rpl_change_master_find_log_pos_err.result b/mysql-test/suite/rpl/r/rpl_change_master_find_log_pos_err.result
new file mode 100644
index 00000000000..0ff76b5b60f
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_change_master_find_log_pos_err.result
@@ -0,0 +1,43 @@
+include/master-slave.inc
+[connection master]
+#
+# Failed CHANGE MASTER TO should not change relay log status
+#
+connection slave;
+include/stop_slave.inc
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+ERROR HY000: Target log not found in binlog index
+SET @@debug_dbug="";
+include/start_slave.inc
+#
+# Ensure relay log can be updated after a failed CHANGE MASTER
+#
+FLUSH RELAY LOGS;
+include/wait_for_slave_param.inc [Relay_Log_File]
+#
+# Slave should continue to receive data from old master after failed
+# CHANGE MASTER TO
+#
+connection master;
+CREATE TABLE t1 (a int);
+insert into t1 values (1);
+connection slave;
+connection slave;
+#
+# Future CHANGE MASTER calls should succeed
+#
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
+include/start_slave.inc
+########################
+# Cleanup
+########################
+connection master;
+DROP TABLE t1;
+connection slave;
+include/stop_slave.inc
+RESET SLAVE ALL;
+change master to master_port=MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+include/start_slave.inc
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_reset_slave_all_clears_filters.result b/mysql-test/suite/rpl/r/rpl_reset_slave_all_clears_filters.result
new file mode 100644
index 00000000000..a273aeaa678
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_reset_slave_all_clears_filters.result
@@ -0,0 +1,54 @@
+include/master-slave.inc
+[connection master]
+connection slave;
+include/stop_slave.inc
+#
+# Category 1) DO_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+#
+# Id filtering variable values should be empty initially
+# Set id filtering variables
+CHANGE MASTER TO DO_DOMAIN_IDS=(1), IGNORE_DOMAIN_IDS=(), IGNORE_SERVER_IDS=(3), MASTER_USE_GTID=SLAVE_POS;
+# do domain id list: 1
+# ignore domain id list:
+# ignore server id list: 3
+# RESET SLAVE ALL should clear values for all id filtering variables
+RESET SLAVE ALL;
+change master to master_port=MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+include/start_slave.inc
+include/stop_slave.inc
+#
+# Category 2) IGNORE_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+#
+# Id filtering variable values should be empty initially
+# Set id filtering variables
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(2), IGNORE_SERVER_IDS=(3), MASTER_USE_GTID=SLAVE_POS;
+# do domain id list:
+# ignore domain id list: 2
+# ignore server id list: 3
+# RESET SLAVE ALL should clear values for all id filtering variables
+RESET SLAVE ALL;
+change master to master_port=MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+include/start_slave.inc
+include/stop_slave.inc
+#
+# Category 3) Null check - edge case with all empty lists to ensure a
+# lack of specification doesn't break anything
+#
+# Id filtering variable values should be empty initially
+# Set id filtering variables
+CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), IGNORE_SERVER_IDS=(), MASTER_USE_GTID=SLAVE_POS;
+# do domain id list:
+# ignore domain id list:
+# ignore server id list:
+# RESET SLAVE ALL should clear values for all id filtering variables
+RESET SLAVE ALL;
+change master to master_port=MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+include/start_slave.inc
+include/stop_slave.inc
+############################
+# Cleanup
+############################
+connection slave;
+change master to master_port=MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+include/start_slave.inc
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test b/mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test
new file mode 100644
index 00000000000..d1c2c03f010
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_change_master_find_log_pos_err.test
@@ -0,0 +1,93 @@
+#
+# Purpose:
+# This test ensures that issuing a CHANGE MASTER will not put a replica into
+# an inconsistent state if the slave cannot find the log files (i.e. the call to
+# find_log_pos in reset_logs fails). More specifically, right before a replica
+# purges the relay logs (part of the `CHANGE MASTER TO` logic), the relay log is
+# temporarily closed with state LOG_TO_BE_OPENED. If the server is issued a
+# CHANGE MASTER and it errors in-between the temporary log closure and purge,
+# i.e. during the function find_log_pos, the log should be closed. The bug
+# reported by MDEV-25284 revealed the log is not properly closed, such that
+# future relay log updates fail, and future CHANGE MASTER calls crash the
+# server.
+#
+# Methodology:
+# This test ensures that the relay log is properly closed by ensuring future
+# updates and CHANGE MASTER calls succeed.
+#
+# References:
+# MDEV-25284: Assertion `info->type == READ_CACHE ||
+# info->type == WRITE_CACHE' failed
+#
+--source include/master-slave.inc
+--source include/have_debug.inc
+
+--echo #
+--echo # Failed CHANGE MASTER TO should not change relay log status
+--echo #
+
+--connection slave
+--source include/stop_slave.inc
+SET @@debug_dbug="d,simulate_find_log_pos_error";
+error 1373;
+CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS;
+SET @@debug_dbug="";
+--source include/start_slave.inc
+
+
+--echo #
+--echo # Ensure relay log can be updated after a failed CHANGE MASTER
+--echo #
+
+FLUSH RELAY LOGS;
+--let $slave_param= Relay_Log_File
+--let $slave_param_value= slave-relay-bin.000003
+--source include/wait_for_slave_param.inc
+
+
+--echo #
+--echo # Slave should continue to receive data from old master after failed
+--echo # CHANGE MASTER TO
+--echo #
+
+--connection master
+CREATE TABLE t1 (a int);
+insert into t1 values (1);
+--let $master_checksum= `CHECKSUM TABLE t1`
+--sync_slave_with_master
+
+--connection slave
+if ($master_checksum != `CHECKSUM TABLE t1`)
+{
+ die("Replica failed to pull data from primary after failed CHANGE MASTER TO");
+}
+
+
+--echo #
+--echo # Future CHANGE MASTER calls should succeed
+--echo #
+
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
+--source include/start_slave.inc
+
+
+--echo ########################
+--echo # Cleanup
+--echo ########################
+
+--connection master
+DROP TABLE t1;
+
+--connection slave
+--source include/stop_slave.inc
+RESET SLAVE ALL;
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+--source include/start_slave.inc
+
+--disable_query_log
+call mtr.add_suppression("Failed to locate old binlog or relay log files");
+--enable_query_log
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test b/mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test
new file mode 100644
index 00000000000..7c01ce16586
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_reset_slave_all_clears_filters.test
@@ -0,0 +1,72 @@
+#
+# Purpose:
+# This test validates that after issuing the `SLAVE RESET ALL` command,
+# any corresponding IGNORE_DOMAIN_IDS/DO_DOMAIN_IDS and IGNORE_SERVER_IDS
+# values are cleared.
+#
+#
+# Methodology:
+# To ensure the filtering variables are properly cleared after issuing
+# SLAVE RESET ALL, we categorize different combinations of allowable input
+# into three different options, and ensure that the variables are cleared for
+# each category. The categories are as follows:
+# Category 1) DO_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+# Category 2) IGNORE_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+# Category 3) Null check - edge case with all empty lists to ensure a lack
+# of specification doesn't break anything
+#
+# To specify the values, the variables are set in `CHANGE MASTER TO`. To
+# ensure the slave state is correct, we test the domain/server id filtering
+# variable values at the following times while testing each category.
+#
+# Before CHANGE MASTER TO the filtering variables are tested to all be
+# empty.
+#
+# After CHANGE MASTER TO the variables are tested to ensure they reflect
+# those set in the CHANGE MASTER command.
+#
+# After RESET SLAVE ALL the filtering variables are tested to all be
+# empty.
+#
+
+--source include/master-slave.inc
+--source include/have_debug.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--echo #
+--echo # Category 1) DO_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+--echo #
+--let $_do_domain_ids= (1)
+--let $_ignore_domain_ids= ()
+--let $_ignore_server_ids= (3)
+--source include/rpl_reset_slave_all_check.inc
+
+--echo #
+--echo # Category 2) IGNORE_DOMAIN_IDS and IGNORE_SERVER_IDS specified together
+--echo #
+--let $_do_domain_ids= ()
+--let $_ignore_domain_ids= (2)
+--let $_ignore_server_ids= (3)
+--source include/rpl_reset_slave_all_check.inc
+
+--echo #
+--echo # Category 3) Null check - edge case with all empty lists to ensure a
+--echo # lack of specification doesn't break anything
+--echo #
+--let $_do_domain_ids= ()
+--let $_ignore_domain_ids= ()
+--let $_ignore_server_ids= ()
+--source include/rpl_reset_slave_all_check.inc
+
+
+--echo ############################
+--echo # Cleanup
+--echo ############################
+--connection slave
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root';
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 45146bc3d49..ec72fb2601d 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -169,6 +169,10 @@ TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY}
${LIBNSL} ${LIBM} ${LIBRT} ${CMAKE_DL_LIBS} ${LIBSOCKET} ${LIBEXECINFO})
DTRACE_INSTRUMENT(mysys)
+IF (HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ TARGET_LINK_LIBRARIES(mysys atomic)
+ENDIF()
+
IF(HAVE_BFD_H)
TARGET_LINK_LIBRARIES(mysys bfd)
ENDIF(HAVE_BFD_H)
diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql
index 2352f801d66..c72d29c3a13 100644
--- a/scripts/mysql_system_tables_fix.sql
+++ b/scripts/mysql_system_tables_fix.sql
@@ -815,7 +815,7 @@ IF 'BASE TABLE' = (select table_type from information_schema.tables where table_
'max_statement_time', max_statement_time,
'plugin', if(plugin>'',plugin,if(length(password)=16,'mysql_old_password','mysql_native_password')),
'authentication_string', if(plugin>'' and authentication_string>'',authentication_string,password),
- 'password_last_changed', if(password_expired='Y', 0, UNIX_TIMESTAMP(password_last_changed)),
+ 'password_last_changed', if(password_expired='Y', 0, if(password_last_changed, UNIX_TIMESTAMP(password_last_changed), UNIX_TIMESTAMP())),
'password_lifetime', ifnull(password_lifetime, -1),
'account_locked', 'Y'=account_locked,
'default_role', default_role,
diff --git a/sql/item.cc b/sql/item.cc
index d696d532d80..2f9f6a25a7e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3812,8 +3812,48 @@ void Item_string::print(String *str, enum_query_type query_type)
}
else
{
- // Caller wants a result in the charset of str_value.
- str_value.print(str);
+ /*
+ We're restoring a parse-able statement from an Item tree.
+ Make sure to revert character set conversions that previously
+ happened in the parser when Item_string was created.
+ */
+ if (print_introducer)
+ {
+ /*
+ Print the string as is, without conversion:
+ Strings with introducers are not converted in the parser.
+ */
+ str_value.print(str);
+ }
+ else
+ {
+ /*
+ Print the string with conversion.
+ Strings without introducers are converted in the parser,
+ from character_set_client to character_set_connection.
+
+ When restoring a CREATE VIEW statement,
+ - str_value.charsets() contains parse time character_set_connection
+ - str->charset() contains parse time character_set_client
+ So we convert the string back from parse-time character_set_connection
+ to parse time character_set_client.
+
+ In some cases, e.g. SHOW PROCEDURE CODE, it's also possible
+ that str->charset() is "utf8mb3" instead of parse time
+ character_set_client. In these cases we convert
+ here from the parse-time character_set_connection to utf8mb3.
+
+ QQ: perhaps the code behind SHOW PROCEDURE CODE should
+ also request the result in the parse-time character_set_client
+ (like the code restoring CREATE VIEW statements does),
+ rather than in utf8mb3:
+ - utf8mb3 does not work well with non-BMP characters (e.g. emoji).
+ - Simply changing utf8mb3 to utf8mb4 will not fully help:
+ some character sets have unassigned characters,
+ they get lost during during cs->utf8mb4->cs round trip.
+ */
+ str_value.print_with_conversion(str, str->charset());
+ }
}
str->append('\'');
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index cf00da79de9..ddf5fc32ea4 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -3569,6 +3569,7 @@ const char *Item_func_json_format::func_name() const
bool Item_func_json_format::fix_length_and_dec()
{
decimals= 0;
+ collation.set(args[0]->collation);
max_length= args[0]->max_length;
maybe_null= 1;
return FALSE;
diff --git a/sql/log.h b/sql/log.h
index e7df904d49e..900e7ef49b9 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -945,6 +945,20 @@ public:
void unlock_binlog_end_pos() { mysql_mutex_unlock(&LOCK_binlog_end_pos); }
mysql_mutex_t* get_binlog_end_pos_lock() { return &LOCK_binlog_end_pos; }
+ /*
+ Ensures the log's state is either LOG_OPEN or LOG_CLOSED. If something
+ failed along the desired path and left the log in invalid state, i.e.
+ LOG_TO_BE_OPENED, forces the state to be LOG_CLOSED.
+ */
+ void try_fix_log_state()
+ {
+ mysql_mutex_lock(get_log_lock());
+ /* Only change the log state if it is LOG_TO_BE_OPENED */
+ if (log_state == LOG_TO_BE_OPENED)
+ log_state= LOG_CLOSED;
+ mysql_mutex_unlock(get_log_lock());
+ }
+
int wait_for_update_binlog_end_pos(THD* thd, struct timespec * timeout);
/*
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index 790d63502de..79f197d4ec3 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -5573,20 +5573,14 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
}
}
-#ifdef HAVE_QUERY_CACHE
-#ifdef WITH_WSREP
+#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE)
/*
Moved invalidation right before the call to rows_event_stmt_cleanup(),
to avoid query cache being polluted with stale entries,
*/
- if (! (WSREP(thd) && wsrep_thd_is_applying(thd)))
- {
-#endif /* WITH_WSREP */
- query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
-#ifdef WITH_WSREP
- }
-#endif /* WITH_WSREP */
-#endif
+ if (WSREP(thd) && wsrep_thd_is_applying(thd))
+ query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
+#endif /* WITH_WSREP && HAVE_QUERY_CACHE */
}
table= m_table= rgi->m_table_map.get_table(m_table_id);
@@ -5787,19 +5781,20 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
restore_empty_query_table_list(thd->lex);
#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE)
- if (WSREP(thd) && wsrep_thd_is_applying(thd))
- {
- query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
- }
+ if (WSREP(thd) && wsrep_thd_is_applying(thd))
+ query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
#endif /* WITH_WSREP && HAVE_QUERY_CACHE */
- if (unlikely(get_flags(STMT_END_F) &&
- (error= rows_event_stmt_cleanup(rgi, thd))))
- slave_rows_error_report(ERROR_LEVEL,
- thd->is_error() ? 0 : error,
- rgi, thd, table,
- get_type_str(),
- RPL_LOG_NAME, log_pos);
+ if (get_flags(STMT_END_F))
+ {
+ if (unlikely((error= rows_event_stmt_cleanup(rgi, thd))))
+ slave_rows_error_report(ERROR_LEVEL, thd->is_error() ? 0 : error,
+ rgi, thd, table, get_type_str(),
+ RPL_LOG_NAME, log_pos);
+ if (thd->slave_thread)
+ free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
+ }
+
DBUG_RETURN(error);
err:
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 0649a8f05e8..17c9029e1a5 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -170,6 +170,8 @@ void Master_info::clear_in_memory_info(bool all)
{
port= MYSQL_PORT;
host[0] = 0; user[0] = 0; password[0] = 0;
+ domain_id_filter.clear_ids();
+ reset_dynamic(&ignore_server_ids);
}
}
@@ -1797,6 +1799,12 @@ void Domain_id_filter::reset_filter()
m_filter= false;
}
+void Domain_id_filter::clear_ids()
+{
+ reset_dynamic(&m_domain_ids[DO_DOMAIN_IDS]);
+ reset_dynamic(&m_domain_ids[IGNORE_DOMAIN_IDS]);
+}
+
/**
Update the do/ignore domain id filter lists.
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
index 4d47689ac18..b6ff69d1f64 100644
--- a/sql/rpl_mi.h
+++ b/sql/rpl_mi.h
@@ -79,6 +79,11 @@ public:
void reset_filter();
/*
+ Clear do_ids and ignore_ids to disable domain id filtering
+ */
+ void clear_ids();
+
+ /*
Update the do/ignore domain id filter lists.
@param do_ids [IN] domain ids to be kept
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 65f053aa09b..9d8d678b052 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3359,21 +3359,22 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth,
const Account_options &options,
const privilege_t privileges)
{
+ ACL_USER_PARAM::AUTH *work_copy= NULL;
if (nauth)
{
- if (acl_user->nauth >= nauth)
- acl_user->nauth= nauth;
- else
- acl_user->alloc_auth(&acl_memroot, nauth);
+ if (!(work_copy= (ACL_USER_PARAM::AUTH*)
+ alloc_root(thd->mem_root, nauth * sizeof(ACL_USER_PARAM::AUTH))))
+ return 1;
USER_AUTH *auth= combo.auth;
for (uint i= 0; i < nauth; i++, auth= auth->next)
{
- acl_user->auth[i].plugin= auth->plugin;
- acl_user->auth[i].auth_string= safe_lexcstrdup_root(&acl_memroot, auth->auth_str);
- if (fix_user_plugin_ptr(acl_user->auth + i))
- acl_user->auth[i].plugin= safe_lexcstrdup_root(&acl_memroot, auth->plugin);
- if (set_user_auth(thd, acl_user->user, acl_user->auth + i, auth->pwtext))
+ work_copy[i].plugin= auth->plugin;
+ work_copy[i].auth_string= safe_lexcstrdup_root(&acl_memroot,
+ auth->auth_str);
+ if (fix_user_plugin_ptr(work_copy + i))
+ work_copy[i].plugin= safe_lexcstrdup_root(&acl_memroot, auth->plugin);
+ if (set_user_auth(thd, acl_user->user, work_copy + i, auth->pwtext))
return 1;
}
}
@@ -3401,11 +3402,34 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth,
if (options.account_locked != ACCOUNTLOCK_UNSPECIFIED)
acl_user->account_locked= options.account_locked == ACCOUNTLOCK_LOCKED;
- /* Unexpire the user password */
+ if (thd->is_error())
+ {
+ // If something went wrong (including OOM) we will not spoil acl cache
+ return 1;
+ }
+ /* Unexpire the user password and copy AUTH (when no more errors possible)*/
if (nauth)
{
acl_user->password_expired= false;
- acl_user->password_last_changed= thd->query_start();;
+ acl_user->password_last_changed= thd->query_start();
+
+ if (acl_user->nauth >= nauth)
+ {
+ acl_user->nauth= nauth;
+ }
+ else
+ {
+ if (acl_user->alloc_auth(&acl_memroot, nauth))
+ {
+ /*
+ acl_user is a copy, so NULL assigned in case of an error do not
+ change the acl cache
+ */
+ return 1;
+ }
+ }
+ DBUG_ASSERT(work_copy); // allocated under the same condinition
+ memcpy(acl_user->auth, work_copy, nauth * sizeof(ACL_USER_PARAM::AUTH));
}
switch (options.password_expire) {
@@ -10195,8 +10219,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
LEX_USER *user_from, LEX_USER *user_to)
{
int result= 0;
- int idx;
int elements;
+ bool restart;
const char *UNINIT_VAR(user);
const char *UNINIT_VAR(host);
ACL_USER *acl_user= NULL;
@@ -10304,82 +10328,98 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
DBUG_RETURN(-1);
}
+
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
struct_no, user_from->user.str, user_from->host.str));
#endif
- /* Loop over all elements *backwards* (see the comment below). */
- for (idx= elements - 1; idx >= 0; idx--)
- {
- /*
- Get a pointer to the element.
- */
- switch (struct_no) {
- case USER_ACL:
- acl_user= dynamic_element(&acl_users, idx, ACL_USER*);
- user= acl_user->user.str;
- host= acl_user->host.hostname;
- break;
+ /* Loop over elements backwards as it may reduce the number of mem-moves
+ for dynamic arrays.
- case DB_ACL:
- acl_db= &acl_dbs.at(idx);
- user= acl_db->user;
- host= acl_db->host.hostname;
+ We restart the loop, if we deleted or updated anything in a hash table
+ because calling my_hash_delete or my_hash_update shuffles elements indices
+ and we can miss some if we do only one scan.
+ */
+ do {
+ restart= false;
+ for (int idx= elements - 1; idx >= 0; idx--)
+ {
+ /*
+ Get a pointer to the element.
+ */
+ switch (struct_no) {
+ case USER_ACL:
+ acl_user= dynamic_element(&acl_users, idx, ACL_USER*);
+ user= acl_user->user.str;
+ host= acl_user->host.hostname;
break;
- case COLUMN_PRIVILEGES_HASH:
- case PROC_PRIVILEGES_HASH:
- case FUNC_PRIVILEGES_HASH:
- case PACKAGE_SPEC_PRIVILEGES_HASH:
- case PACKAGE_BODY_PRIVILEGES_HASH:
- grant_name= (GRANT_NAME*) my_hash_element(grant_name_hash, idx);
- user= grant_name->user;
- host= grant_name->host.hostname;
- break;
+ case DB_ACL:
+ acl_db= &acl_dbs.at(idx);
+ user= acl_db->user;
+ host= acl_db->host.hostname;
+ break;
- case PROXY_USERS_ACL:
- acl_proxy_user= dynamic_element(&acl_proxy_users, idx, ACL_PROXY_USER*);
- user= acl_proxy_user->get_user();
- host= acl_proxy_user->get_host();
- break;
+ case COLUMN_PRIVILEGES_HASH:
+ case PROC_PRIVILEGES_HASH:
+ case FUNC_PRIVILEGES_HASH:
+ case PACKAGE_SPEC_PRIVILEGES_HASH:
+ case PACKAGE_BODY_PRIVILEGES_HASH:
+ grant_name= (GRANT_NAME*) my_hash_element(grant_name_hash, idx);
+ user= grant_name->user;
+ host= grant_name->host.hostname;
+ break;
- case ROLES_MAPPINGS_HASH:
- role_grant_pair= (ROLE_GRANT_PAIR *) my_hash_element(roles_mappings_hash, idx);
- user= role_grant_pair->u_uname;
- host= role_grant_pair->u_hname;
- break;
+ case PROXY_USERS_ACL:
+ acl_proxy_user= dynamic_element(&acl_proxy_users, idx, ACL_PROXY_USER*);
+ user= acl_proxy_user->get_user();
+ host= acl_proxy_user->get_host();
+ break;
- default:
- DBUG_ASSERT(0);
- }
- if (! host)
- host= "";
+ case ROLES_MAPPINGS_HASH:
+ role_grant_pair= (ROLE_GRANT_PAIR *) my_hash_element(roles_mappings_hash, idx);
+ user= role_grant_pair->u_uname;
+ host= role_grant_pair->u_hname;
+ break;
+
+ default:
+ DBUG_ASSERT(0);
+ }
+ if (! host)
+ host= "";
#ifdef EXTRA_DEBUG
- DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'",
- struct_no, idx, user, host));
+ DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'",
+ struct_no, idx, user, host));
#endif
- if (struct_no == ROLES_MAPPINGS_HASH)
- {
- const char* role= role_grant_pair->r_uname? role_grant_pair->r_uname: "";
- if (user_from->is_role())
+ if (struct_no == ROLES_MAPPINGS_HASH)
{
- /* When searching for roles within the ROLES_MAPPINGS_HASH, we have
- to check both the user field as well as the role field for a match.
+ const char* role= role_grant_pair->r_uname? role_grant_pair->r_uname: "";
+ if (user_from->is_role())
+ {
+ /* When searching for roles within the ROLES_MAPPINGS_HASH, we have
+ to check both the user field as well as the role field for a match.
- It is possible to have a role granted to a role. If we are going
- to modify the mapping entry, it needs to be done on either on the
- "user" end (here represented by a role) or the "role" end. At least
- one part must match.
+ It is possible to have a role granted to a role. If we are going
+ to modify the mapping entry, it needs to be done on either on the
+ "user" end (here represented by a role) or the "role" end. At least
+ one part must match.
- If the "user" end has a not-empty host string, it can never match
- as we are searching for a role here. A role always has an empty host
- string.
- */
- if ((*host || strcmp(user_from->user.str, user)) &&
- strcmp(user_from->user.str, role))
- continue;
+ If the "user" end has a not-empty host string, it can never match
+ as we are searching for a role here. A role always has an empty host
+ string.
+ */
+ if ((*host || strcmp(user_from->user.str, user)) &&
+ strcmp(user_from->user.str, role))
+ continue;
+ }
+ else
+ {
+ if (strcmp(user_from->user.str, user) ||
+ my_strcasecmp(system_charset_info, user_from->host.str, host))
+ continue;
+ }
}
else
{
@@ -10387,157 +10427,134 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
my_strcasecmp(system_charset_info, user_from->host.str, host))
continue;
}
- }
- else
- {
- if (strcmp(user_from->user.str, user) ||
- my_strcasecmp(system_charset_info, user_from->host.str, host))
- continue;
- }
- result= 1; /* At least one element found. */
- if ( drop )
- {
- elements--;
- switch ( struct_no ) {
- case USER_ACL:
- free_acl_user(dynamic_element(&acl_users, idx, ACL_USER*));
- delete_dynamic_element(&acl_users, idx);
- break;
+ result= 1; /* At least one element found. */
+ if ( drop )
+ {
+ elements--;
+ switch ( struct_no ) {
+ case USER_ACL:
+ free_acl_user(dynamic_element(&acl_users, idx, ACL_USER*));
+ delete_dynamic_element(&acl_users, idx);
+ break;
- case DB_ACL:
- acl_dbs.del(idx);
- break;
+ case DB_ACL:
+ acl_dbs.del(idx);
+ break;
- case COLUMN_PRIVILEGES_HASH:
- case PROC_PRIVILEGES_HASH:
- case FUNC_PRIVILEGES_HASH:
- case PACKAGE_SPEC_PRIVILEGES_HASH:
- case PACKAGE_BODY_PRIVILEGES_HASH:
- my_hash_delete(grant_name_hash, (uchar*) grant_name);
- /*
- In our HASH implementation on deletion one elements
- is moved into a place where a deleted element was,
- and the last element is moved into the empty space.
- Thus we need to re-examine the current element, but
- we don't have to restart the search from the beginning.
- */
- if (idx != elements)
- idx++;
- break;
+ case COLUMN_PRIVILEGES_HASH:
+ case PROC_PRIVILEGES_HASH:
+ case FUNC_PRIVILEGES_HASH:
+ case PACKAGE_SPEC_PRIVILEGES_HASH:
+ case PACKAGE_BODY_PRIVILEGES_HASH:
+ my_hash_delete(grant_name_hash, (uchar*) grant_name);
+ restart= true;
+ break;
- case PROXY_USERS_ACL:
- delete_dynamic_element(&acl_proxy_users, idx);
- break;
+ case PROXY_USERS_ACL:
+ delete_dynamic_element(&acl_proxy_users, idx);
+ break;
- case ROLES_MAPPINGS_HASH:
- my_hash_delete(roles_mappings_hash, (uchar*) role_grant_pair);
- if (idx != elements)
- idx++;
- break;
+ case ROLES_MAPPINGS_HASH:
+ my_hash_delete(roles_mappings_hash, (uchar*) role_grant_pair);
+ restart= true;
+ break;
- default:
- DBUG_ASSERT(0);
- break;
+ default:
+ DBUG_ASSERT(0);
+ break;
+ }
}
- }
- else if ( user_to )
- {
- switch ( struct_no ) {
- case USER_ACL:
- acl_user->user= safe_lexcstrdup_root(&acl_memroot, user_to->user);
- update_hostname(&acl_user->host, strdup_root(&acl_memroot, user_to->host.str));
- acl_user->hostname_length= strlen(acl_user->host.hostname);
- break;
-
- case DB_ACL:
- acl_db->user= strdup_root(&acl_memroot, user_to->user.str);
- update_hostname(&acl_db->host, strdup_root(&acl_memroot, user_to->host.str));
- break;
+ else if ( user_to )
+ {
+ switch ( struct_no ) {
+ case USER_ACL:
+ acl_user->user= safe_lexcstrdup_root(&acl_memroot, user_to->user);
+ update_hostname(&acl_user->host, strdup_root(&acl_memroot, user_to->host.str));
+ acl_user->hostname_length= strlen(acl_user->host.hostname);
+ break;
- case COLUMN_PRIVILEGES_HASH:
- case PROC_PRIVILEGES_HASH:
- case FUNC_PRIVILEGES_HASH:
- case PACKAGE_SPEC_PRIVILEGES_HASH:
- case PACKAGE_BODY_PRIVILEGES_HASH:
- {
- /*
- Save old hash key and its length to be able to properly update
- element position in hash.
- */
- char *old_key= grant_name->hash_key;
- size_t old_key_length= grant_name->key_length;
+ case DB_ACL:
+ acl_db->user= strdup_root(&acl_memroot, user_to->user.str);
+ update_hostname(&acl_db->host, strdup_root(&acl_memroot, user_to->host.str));
+ break;
- /*
- Update the grant structure with the new user name and host name.
- */
- grant_name->set_user_details(user_to->host.str, grant_name->db,
- user_to->user.str, grant_name->tname,
- TRUE);
+ case COLUMN_PRIVILEGES_HASH:
+ case PROC_PRIVILEGES_HASH:
+ case FUNC_PRIVILEGES_HASH:
+ case PACKAGE_SPEC_PRIVILEGES_HASH:
+ case PACKAGE_BODY_PRIVILEGES_HASH:
+ {
+ /*
+ Save old hash key and its length to be able to properly update
+ element position in hash.
+ */
+ char *old_key= grant_name->hash_key;
+ size_t old_key_length= grant_name->key_length;
+
+ /*
+ Update the grant structure with the new user name and host name.
+ */
+ grant_name->set_user_details(user_to->host.str, grant_name->db,
+ user_to->user.str, grant_name->tname,
+ TRUE);
+
+ /*
+ Since username is part of the hash key, when the user name
+ is renamed, the hash key is changed. Update the hash to
+ ensure that the position matches the new hash key value
+ */
+ my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
+ old_key_length);
+ restart= true;
+ break;
+ }
- /*
- Since username is part of the hash key, when the user name
- is renamed, the hash key is changed. Update the hash to
- ensure that the position matches the new hash key value
- */
- my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
- old_key_length);
- /*
- hash_update() operation could have moved element from the tail or
- the head of the hash to the current position. But it can never
- move an element from the head to the tail or from the tail to the
- head over the current element.
- So we need to examine the current element once again, but
- we don't need to restart the search from the beginning.
- */
- idx++;
+ case PROXY_USERS_ACL:
+ acl_proxy_user->set_user (&acl_memroot, user_to->user.str);
+ acl_proxy_user->set_host (&acl_memroot, user_to->host.str);
break;
- }
- case PROXY_USERS_ACL:
- acl_proxy_user->set_user (&acl_memroot, user_to->user.str);
- acl_proxy_user->set_host (&acl_memroot, user_to->host.str);
- break;
+ case ROLES_MAPPINGS_HASH:
+ {
+ /*
+ Save old hash key and its length to be able to properly update
+ element position in hash.
+ */
+ char *old_key= role_grant_pair->hashkey.str;
+ size_t old_key_length= role_grant_pair->hashkey.length;
+ bool oom;
+
+ if (user_to->is_role())
+ oom= role_grant_pair->init(&acl_memroot, role_grant_pair->u_uname,
+ role_grant_pair->u_hname,
+ user_to->user.str, false);
+ else
+ oom= role_grant_pair->init(&acl_memroot, user_to->user.str,
+ user_to->host.str,
+ role_grant_pair->r_uname, false);
+ if (oom)
+ DBUG_RETURN(-1);
+
+ my_hash_update(roles_mappings_hash, (uchar*) role_grant_pair,
+ (uchar*) old_key, old_key_length);
+ restart= true;
+ break;
+ }
- case ROLES_MAPPINGS_HASH:
- {
- /*
- Save old hash key and its length to be able to properly update
- element position in hash.
- */
- char *old_key= role_grant_pair->hashkey.str;
- size_t old_key_length= role_grant_pair->hashkey.length;
- bool oom;
-
- if (user_to->is_role())
- oom= role_grant_pair->init(&acl_memroot, role_grant_pair->u_uname,
- role_grant_pair->u_hname,
- user_to->user.str, false);
- else
- oom= role_grant_pair->init(&acl_memroot, user_to->user.str,
- user_to->host.str,
- role_grant_pair->r_uname, false);
- if (oom)
- DBUG_RETURN(-1);
-
- my_hash_update(roles_mappings_hash, (uchar*) role_grant_pair,
- (uchar*) old_key, old_key_length);
- idx++; // see the comment above
+ default:
+ DBUG_ASSERT(0);
break;
}
- default:
- DBUG_ASSERT(0);
+ }
+ else
+ {
+ /* If search is requested, we do not need to search further. */
break;
}
-
}
- else
- {
- /* If search is requested, we do not need to search further. */
- break;
- }
- }
+ } while (restart);
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("scan struct: %u result %d", struct_no, result));
#endif
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 73bfb8227e1..eab33a79b38 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -784,6 +784,9 @@ retry:
if (!(handler= mysql_ha_find_handler(thd, &tables->alias)))
goto err0;
+ if (thd->transaction->xid_state.check_has_uncommitted_xa())
+ goto err0;
+
table= handler->table;
tables->table= table; // This is used by fix_fields
table->pos_in_table_list= tables;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index c49ea7d5908..e15980e9b3c 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3949,6 +3949,16 @@ err:
mi->unlock_slave_threads();
if (ret == FALSE)
my_ok(thd);
+ else
+ {
+ /*
+ Depending on where CHANGE MASTER failed, the logs may be waiting to be
+ reopened. This would break future log updates and CHANGE MASTER calls.
+ `try_fix_log_state()` allows the relay log to fix its state to no longer
+ expect to be reopened.
+ */
+ mi->rli.relay_log.try_fix_log_state();
+ }
DBUG_RETURN(ret);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ec1630b01b0..e90fe4079fd 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -27971,6 +27971,11 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
//Item List
bool first= 1;
+ /*
+ outer_select() can not be used here because it is for name resolution
+ and will return NULL at any end of name resolution chain (view/derived)
+ */
+ bool top_level= (get_master()->get_master() == 0);
List_iterator_fast<Item> it(item_list);
Item *item;
while ((item= it++))
@@ -27980,7 +27985,8 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
else
str->append(',');
- if (is_subquery_function() && item->is_autogenerated_name())
+ if ((is_subquery_function() && item->is_autogenerated_name()) ||
+ !item->name.str)
{
/*
Do not print auto-generated aliases in subqueries. It has no purpose
@@ -27989,7 +27995,20 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
item->print(str, query_type);
}
else
- item->print_item_w_name(str, query_type);
+ {
+ /*
+ Do not print illegal names (if it is not top level SELECT).
+ Top level view checked (and correct name are assigned),
+ other cases of top level SELECT are not important, because
+ it is not "table field".
+ */
+ if (top_level ||
+ !item->is_autogenerated_name() ||
+ !check_column_name(item->name.str))
+ item->print_item_w_name(str, query_type);
+ else
+ item->print(str, query_type);
+ }
}
/*
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 04c2e959a3c..f4fc8d2decf 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4450,7 +4450,9 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names,
if (!lookup_field_vals->wild_table_value &&
lookup_field_vals->table_value.str)
{
- if (lookup_field_vals->table_value.length > NAME_LEN)
+ if (check_table_name(lookup_field_vals->table_value.str,
+ lookup_field_vals->table_value.length,
+ false))
{
/*
Impossible value for a table name,
@@ -4487,6 +4489,9 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names,
return (schema_tables_add(thd, table_names,
lookup_field_vals->table_value.str));
+ if (check_db_name((LEX_STRING*)db_name))
+ return 0; // Impossible TABLE_SCHEMA name
+
find_files_result res= find_files(thd, table_names, db_name, path,
&lookup_field_vals->table_value);
if (res != FIND_FILES_OK)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index d28ba06e963..92fd6dd3ea6 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4229,8 +4229,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
/* Align key length to multibyte char boundary */
key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
}
- else
- is_hash_field_needed= true;
}
}
// Catch invalid use of partial keys
@@ -4276,11 +4274,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
else
{
- if (key->type == Key::UNIQUE)
- {
- is_hash_field_needed= true;
- }
- else
+ if (key->type != Key::UNIQUE)
{
key_part_length= MY_MIN(max_key_length, file->max_key_part_length());
my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
@@ -4289,6 +4283,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
+ if (key->type == Key::UNIQUE
+ && key_part_length > MY_MIN(max_key_length,
+ file->max_key_part_length()))
+ is_hash_field_needed= true;
+
/* We can not store key_part_length more then 2^16 - 1 in frm */
if (is_hash_field_needed && column->length > UINT_MAX16)
{
@@ -4323,7 +4322,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
unique_key=1;
key_info->key_length=(uint16) key_length;
if (key_info->key_length > max_key_length && key->type == Key::UNIQUE)
- is_hash_field_needed= true;
+ is_hash_field_needed= true; // for case "a BLOB UNIQUE"
if (key_length > max_key_length && key->type != Key::FULLTEXT &&
!is_hash_field_needed)
{
diff --git a/sql/table.cc b/sql/table.cc
index ba7461ed7a5..e06c4db81f0 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4946,6 +4946,21 @@ bool check_table_name(const char *name, size_t length, bool check_for_path_chars
if (check_for_path_chars &&
(*name == '/' || *name == '\\' || *name == '~' || *name == FN_EXTCHAR))
return 1;
+ /*
+ We don't allow zero byte in table/schema names:
+ - Some code still uses NULL-terminated strings.
+ Zero bytes will confuse this code.
+ - There is a little practical use of zero bytes in names anyway.
+ Note, if the string passed as "name" comes here
+ from the parser as an identifier, it does not contain zero bytes,
+ as the parser rejects zero bytes in identifiers.
+ But "name" can also come here from queries like this:
+ SELECT * FROM I_S.TABLES WHERE TABLE_NAME='str';
+ In this case "name" is a general string expression
+ and it can have any arbitrary bytes, including zero bytes.
+ */
+ if (*name == 0x00)
+ return 1;
name++;
name_length++;
}
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index 40d9751721e..78dce431869 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -268,14 +268,14 @@ bool TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
template <class TYPE>
char *TYPBLK<TYPE>::GetCharString(char *p, int n)
{
- sprintf(p, Fmt, Typp[n]);
+ sprintf(p, Fmt, UnalignedRead(n));
return p;
} // end of GetCharString
template <>
char *TYPBLK<double>::GetCharString(char *p, int n)
{
- sprintf(p, Fmt, Prec, Typp[n]);
+ sprintf(p, Fmt, Prec, UnalignedRead(n));
return p;
} // end of GetCharString
@@ -291,7 +291,7 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, int n)
ChkTyp(valp);
if (!(b = valp->IsNull()))
- Typp[n] = GetTypedValue(valp);
+ UnalignedWrite(n, GetTypedValue(valp));
else
Reset(n);
@@ -353,9 +353,9 @@ void TYPBLK<TYPE>::SetValue(PCSZ p, int n)
ulonglong val = CharToNumber(p, strlen(p), maxval, Unsigned, &minus);
if (minus && val < maxval)
- Typp[n] = (TYPE)(-(signed)val);
+ UnalignedWrite(n, (TYPE)(-(signed)val));
else
- Typp[n] = (TYPE)val;
+ UnalignedWrite(n, (TYPE)val);
SetNull(n, false);
} // end of SetValue
@@ -398,7 +398,7 @@ void TYPBLK<double>::SetValue(PCSZ p, int n)
throw Type;
} // endif Check
- Typp[n] = atof(p);
+ UnalignedWrite(n, atof(p));
SetNull(n, false);
} // end of SetValue
@@ -430,7 +430,7 @@ void TYPBLK<TYPE>::SetValue(PVBLK pv, int n1, int n2)
ChkTyp(pv);
if (!(b = pv->IsNull(n2) && Nullable))
- Typp[n1] = GetTypedValue(pv, n2);
+ UnalignedWrite(n1, GetTypedValue(pv, n2));
else
Reset(n1);
@@ -481,10 +481,10 @@ void TYPBLK<TYPE>::SetMin(PVAL valp, int n)
{
CheckParms(valp, n)
TYPE tval = GetTypedValue(valp);
- TYPE& tmin = Typp[n];
+ TYPE tmin = UnalignedRead(n);
if (tval < tmin)
- tmin = tval;
+ UnalignedWrite(n, tval);
} // end of SetMin
@@ -496,10 +496,10 @@ void TYPBLK<TYPE>::SetMax(PVAL valp, int n)
{
CheckParms(valp, n)
TYPE tval = GetTypedValue(valp);
- TYPE& tmin = Typp[n];
+ TYPE tmin = UnalignedRead(n);
if (tval > tmin)
- tmin = tval;
+ UnalignedWrite(n, tval);
} // end of SetMax
@@ -513,8 +513,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, int k, int n)
CheckType(pv)
TYPE *lp = ((TYPBLK*)pv)->Typp;
- for (int i = k; i < n; i++) // TODO
- Typp[i] = lp[i];
+ memcpy(Typp + k, lp + k, sizeof(TYPE) * n);
} // end of SetValues
#endif // 0
@@ -525,7 +524,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, int k, int n)
template <class TYPE>
void TYPBLK<TYPE>::Move(int i, int j)
{
- Typp[j] = Typp[i];
+ UnalignedWrite(j, UnalignedRead(i));
MoveNull(i, j);
} // end of Move
@@ -539,7 +538,7 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n)
ChkIndx(n);
ChkTyp(vp);
#endif // _DEBUG
- TYPE mlv = Typp[n];
+ TYPE mlv = UnalignedRead(n);
TYPE vlv = GetTypedValue(vp);
return (vlv > mlv) ? 1 : (vlv < mlv) ? (-1) : 0;
@@ -551,8 +550,8 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n)
template <class TYPE>
int TYPBLK<TYPE>::CompVal(int i1, int i2)
{
- TYPE lv1 = Typp[i1];
- TYPE lv2 = Typp[i2];
+ TYPE lv1 = UnalignedRead(i1);
+ TYPE lv2 = UnalignedRead(i2);
return (lv1 > lv2) ? 1 : (lv1 < lv2) ? (-1) : 0;
} // end of CompVal
@@ -589,7 +588,7 @@ int TYPBLK<TYPE>::Find(PVAL vp)
TYPE n = GetTypedValue(vp);
for (i = 0; i < Nval; i++)
- if (n == Typp[i])
+ if (n == UnalignedRead(i))
break;
return (i < Nval) ? i : (-1);
@@ -605,7 +604,7 @@ int TYPBLK<TYPE>::GetMaxLength(void)
int i, n, m;
for (i = n = 0; i < Nval; i++) {
- m = sprintf(buf, Fmt, Typp[i]);
+ m = sprintf(buf, Fmt, UnalignedRead(i));
n = MY_MAX(n, m);
} // endfor i
@@ -1335,7 +1334,7 @@ char *DATBLK::GetCharString(char *p, int n)
char *vp;
if (Dvalp) {
- Dvalp->SetValue(Typp[n]);
+ Dvalp->SetValue(UnalignedRead(n));
vp = Dvalp->GetCharString(p);
} else
vp = TYPBLK<int>::GetCharString(p, n);
@@ -1351,7 +1350,7 @@ void DATBLK::SetValue(PCSZ p, int n)
if (Dvalp) {
// Decode the string according to format
Dvalp->SetValue_psz(p);
- Typp[n] = Dvalp->GetIntValue();
+ UnalignedWrite(n, Dvalp->GetIntValue());
} else
TYPBLK<int>::SetValue(p, n);
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index 568fc172c6a..537e838c99f 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -151,40 +151,41 @@ class TYPBLK : public VALBLK {
// Implementation
virtual bool Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(TYPE);}
- virtual char GetTinyValue(int n) {return (char)Typp[n];}
- virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
- virtual short GetShortValue(int n) {return (short)Typp[n];}
- virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];}
- virtual int GetIntValue(int n) {return (int)Typp[n];}
- virtual uint GetUIntValue(int n) {return (uint)Typp[n];}
- virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
- virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
- virtual double GetFloatValue(int n) {return (double)Typp[n];}
+
+ virtual char GetTinyValue(int n) {return (char)UnalignedRead(n);}
+ virtual uchar GetUTinyValue(int n) {return (uchar)UnalignedRead(n);}
+ virtual short GetShortValue(int n) {return (short)UnalignedRead(n);}
+ virtual ushort GetUShortValue(int n) {return (ushort)UnalignedRead(n);}
+ virtual int GetIntValue(int n) {return (int)UnalignedRead(n);}
+ virtual uint GetUIntValue(int n) {return (uint)UnalignedRead(n);}
+ virtual longlong GetBigintValue(int n) {return (longlong)UnalignedRead(n);}
+ virtual ulonglong GetUBigintValue(int n) {return (ulonglong)UnalignedRead(n);}
+ virtual double GetFloatValue(int n) {return (double)UnalignedRead(n);}
virtual char *GetCharString(char *p, int n);
- virtual void Reset(int n) {Typp[n] = 0;}
+ virtual void Reset(int n) {UnalignedWrite(n, 0);}
// Methods
using VALBLK::SetValue;
virtual void SetValue(PCSZ sp, int n);
virtual void SetValue(const char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
- {Typp[n] = (TYPE)sval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
virtual void SetValue(ushort sval, int n)
- {Typp[n] = (TYPE)sval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
virtual void SetValue(int lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(uint lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(longlong lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(ulonglong lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(double fval, int n)
- {Typp[n] = (TYPE)fval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)fval); SetNull(n, false);}
virtual void SetValue(char cval, int n)
- {Typp[n] = (TYPE)cval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
virtual void SetValue(uchar cval, int n)
- {Typp[n] = (TYPE)cval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetMin(PVAL valp, int n);
@@ -206,6 +207,17 @@ class TYPBLK : public VALBLK {
// Members
TYPE* const &Typp;
const char *Fmt;
+
+ // Unaligned access
+ TYPE UnalignedRead(int n) const {
+ TYPE result;
+ memcpy(&result, Typp + n, sizeof(TYPE));
+ return result;
+ }
+
+ void UnalignedWrite(int n, TYPE value) {
+ memcpy(Typp + n, &value, sizeof(TYPE));
+ }
}; // end of class TYPBLK
/***********************************************************************/
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 1329cd95117..7a95b19678c 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -150,7 +150,7 @@ SET(INNOBASE_SOURCES
include/fts0tokenize.h
include/fts0types.h
include/fts0types.ic
- include/fts0vlc.ic
+ include/fts0vlc.h
include/fut0fut.h
include/fut0lst.h
include/gis0geo.h
@@ -399,3 +399,7 @@ IF(NOT (PLUGIN_INNOBASE STREQUAL DYNAMIC))
TARGET_LINK_LIBRARIES(innobase tpool mysys)
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/extra/mariabackup ${CMAKE_BINARY_DIR}/extra/mariabackup)
ENDIF()
+
+IF(WITH_UNIT_TESTS)
+ ADD_SUBDIRECTORY(unittest)
+ENDIF()
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index ff99a2d7e2a..0225099836c 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -32,7 +32,7 @@ Full Text Search interface
#include "fts0priv.h"
#include "fts0types.h"
#include "fts0types.ic"
-#include "fts0vlc.ic"
+#include "fts0vlc.h"
#include "fts0plugin.h"
#include "dict0priv.h"
#include "dict0stats.h"
@@ -579,6 +579,7 @@ fts_cache_init(
cache->sync_heap->arg = mem_heap_create(1024);
cache->total_size = 0;
+ cache->total_size_at_sync = 0;
mutex_enter((ib_mutex_t*) &cache->deleted_lock);
cache->deleted_doc_ids = ib_vector_create(
@@ -1233,7 +1234,7 @@ fts_cache_node_add_positions(
ulint enc_len;
ulint last_pos;
byte* ptr_start;
- ulint doc_id_delta;
+ doc_id_t doc_id_delta;
#ifdef UNIV_DEBUG
if (cache) {
@@ -1244,7 +1245,7 @@ fts_cache_node_add_positions(
ut_ad(doc_id >= node->last_doc_id);
/* Calculate the space required to store the ilist. */
- doc_id_delta = (ulint)(doc_id - node->last_doc_id);
+ doc_id_delta = doc_id - node->last_doc_id;
enc_len = fts_get_encoded_len(doc_id_delta);
last_pos = 0;
@@ -1293,14 +1294,14 @@ fts_cache_node_add_positions(
ptr_start = ptr;
/* Encode the new fragment. */
- ptr += fts_encode_int(doc_id_delta, ptr);
+ ptr = fts_encode_int(doc_id_delta, ptr);
last_pos = 0;
for (i = 0; i < ib_vector_size(positions); i++) {
ulint pos = *(static_cast<ulint*>(
ib_vector_get(positions, i)));
- ptr += fts_encode_int(pos - last_pos, ptr);
+ ptr = fts_encode_int(pos - last_pos, ptr);
last_pos = pos;
}
@@ -3523,11 +3524,14 @@ fts_add_doc_by_id(
get_doc->index_cache,
doc_id, doc.tokens);
- bool need_sync = false;
- if ((cache->total_size > fts_max_cache_size / 10
- || fts_need_sync)
- && !cache->sync->in_progress) {
- need_sync = true;
+ bool need_sync = !cache->sync->in_progress
+ && (fts_need_sync
+ || (cache->total_size
+ - cache->total_size_at_sync)
+ > fts_max_cache_size / 10);
+ if (need_sync) {
+ cache->total_size_at_sync =
+ cache->total_size;
}
rw_lock_x_unlock(&table->fts->cache->lock);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 52a7428f941..c288dfee6f8 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -36,6 +36,7 @@ Completed 2011/7/10 Sunny and Jimmy Yang
#include "ut0list.h"
#include "zlib.h"
#include "fts0opt.h"
+#include "fts0vlc.h"
/** The FTS optimize thread's work queue. */
ib_wqueue_t* fts_optimize_wq;
@@ -1122,7 +1123,7 @@ fts_optimize_encode_node(
ulint pos_enc_len;
doc_id_t doc_id_delta;
dberr_t error = DB_SUCCESS;
- byte* src = enc->src_ilist_ptr;
+ const byte* src = enc->src_ilist_ptr;
if (node->first_doc_id == 0) {
ut_a(node->last_doc_id == 0);
@@ -1179,7 +1180,7 @@ fts_optimize_encode_node(
/* Encode the doc id. Cast to ulint, the delta should be small and
therefore no loss of precision. */
- dst += fts_encode_int((ulint) doc_id_delta, dst);
+ dst = fts_encode_int(doc_id_delta, dst);
/* Copy the encoded pos array. */
memcpy(dst, src, pos_enc_len);
@@ -1226,7 +1227,8 @@ fts_optimize_node(
doc_id_t delta;
doc_id_t del_doc_id = FTS_NULL_DOC_ID;
- delta = fts_decode_vlc(&enc->src_ilist_ptr);
+ delta = fts_decode_vlc(
+ (const byte**)&enc->src_ilist_ptr);
test_again:
/* Check whether the doc id is in the delete list, if
@@ -1254,7 +1256,7 @@ test_again:
/* Skip the entries for this document. */
while (*enc->src_ilist_ptr) {
- fts_decode_vlc(&enc->src_ilist_ptr);
+ fts_decode_vlc((const byte**)&enc->src_ilist_ptr);
}
/* Skip the end of word position marker. */
@@ -2667,6 +2669,9 @@ fts_optimize_request_sync_table(
table->fts->sync_message = true;
+ DBUG_EXECUTE_IF("fts_optimize_wq_count_check",
+ DBUG_ASSERT(fts_optimize_wq->length <= 1000););
+
mutex_exit(&fts_optimize_wq->mutex);
}
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index 304a3315342..2964748d330 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -34,6 +34,7 @@ Completed 2011/7/10 Sunny and Jimmy Yang
#include "fts0pars.h"
#include "fts0types.h"
#include "fts0plugin.h"
+#include "fts0vlc.h"
#include <iomanip>
#include <vector>
@@ -3225,7 +3226,7 @@ fts_query_filter_doc_ids(
ulint len, /*!< in: doc id ilist size */
ibool calc_doc_count) /*!< in: whether to remember doc count */
{
- byte* ptr = static_cast<byte*>(data);
+ const byte* ptr = static_cast<byte*>(data);
doc_id_t doc_id = 0;
ulint decoded = 0;
ib_rbt_t* doc_freqs = word_freq->doc_freqs;
@@ -3235,8 +3236,8 @@ fts_query_filter_doc_ids(
ulint freq = 0;
fts_doc_freq_t* doc_freq;
fts_match_t* match = NULL;
- ulint last_pos = 0;
- ulint pos = fts_decode_vlc(&ptr);
+ doc_id_t last_pos = 0;
+ doc_id_t pos = fts_decode_vlc(&ptr);
/* Some sanity checks. */
if (doc_id == 0) {
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c2d98906e52..7d3eb64e5a0 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7965,8 +7965,7 @@ calc_row_difference(
&& prebuilt->table->fts
&& innobase_strcasecmp(
field->field_name.str, FTS_DOC_ID_COL_NAME) == 0) {
- doc_id = (doc_id_t) mach_read_from_n_little_endian(
- n_ptr, 8);
+ doc_id = mach_read_uint64_little_endian(n_ptr);
if (doc_id == 0) {
return(DB_FTS_INVALID_DOCID);
}
@@ -8209,16 +8208,6 @@ calc_row_difference(
<< innodb_table->name;
return(DB_FTS_INVALID_DOCID);
- } else if ((doc_id
- - prebuilt->table->fts->cache->next_doc_id)
- >= FTS_DOC_ID_MAX_STEP) {
-
- ib::warn() << "Doc ID " << doc_id << " is too"
- " big. Its difference with largest"
- " Doc ID used " << prebuilt->table->fts
- ->cache->next_doc_id - 1
- << " cannot exceed or equal to "
- << FTS_DOC_ID_MAX_STEP;
}
@@ -11351,10 +11340,6 @@ bool create_table_info_t::innobase_table_flags()
ut_min(static_cast<ulint>(UNIV_PAGE_SSIZE_MAX),
static_cast<ulint>(PAGE_ZIP_SSIZE_MAX));
- /* Cache the value of innobase_compression_level, in case it is
- modified by another thread while the table is being created. */
- const ulint default_compression_level = page_zip_level;
-
ha_table_option_struct *options= m_form->s->option_struct;
m_flags = 0;
@@ -11543,12 +11528,23 @@ index_bad:
m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE;
}
+ ulint level = ulint(options->page_compression_level);
+ if (!level) {
+ level = page_zip_level;
+ if (!level && options->page_compressed) {
+ push_warning_printf(
+ m_thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: PAGE_COMPRESSED requires"
+ " PAGE_COMPRESSION_LEVEL or"
+ " innodb_compression_level > 0");
+ DBUG_RETURN(false);
+ }
+ }
+
/* Set the table flags */
dict_tf_set(&m_flags, innodb_row_format, zip_ssize,
- m_use_data_dir,
- options->page_compressed,
- options->page_compression_level == 0 ?
- default_compression_level : ulint(options->page_compression_level));
+ m_use_data_dir, options->page_compressed, level);
if (m_form->s->table_type == TABLE_TYPE_SEQUENCE) {
m_flags |= DICT_TF_MASK_NO_ROLLBACK;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index aee8d33ac78..1f748b5a932 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -7728,6 +7728,8 @@ check_if_ok_to_rename:
}
if (!info.innobase_table_flags()) {
+ my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
+ table_type(), "PAGE_COMPRESSED");
goto err_exit_no_heap;
}
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index dfc2af6eb43..c6ffbb5b9ea 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -58,6 +58,7 @@ Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits)
#include "fil0fil.h"
#include "fil0crypt.h"
#include "dict0crea.h"
+#include "fts0vlc.h"
/** The latest successfully looked up innodb_fts_aux_table */
UNIV_INTERN table_id_t innodb_ft_aux_table_id;
@@ -2717,7 +2718,7 @@ i_s_fts_index_cache_fill_one_index(
/* Decrypt the ilist, and display Dod ID and word position */
for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
fts_node_t* node;
- byte* ptr;
+ const byte* ptr;
ulint decoded = 0;
doc_id_t doc_id = 0;
@@ -2727,13 +2728,11 @@ i_s_fts_index_cache_fill_one_index(
ptr = node->ilist;
while (decoded < node->ilist_size) {
- ulint pos = fts_decode_vlc(&ptr);
- doc_id += pos;
+ doc_id += fts_decode_vlc(&ptr);
/* Get position info */
while (*ptr) {
- pos = fts_decode_vlc(&ptr);
OK(field_store_string(
fields[I_S_FTS_WORD],
@@ -2754,7 +2753,7 @@ i_s_fts_index_cache_fill_one_index(
doc_id, true));
OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
- pos, true));
+ fts_decode_vlc(&ptr), true));
OK(schema_table_store_record(
thd, table));
@@ -3088,7 +3087,7 @@ i_s_fts_index_table_fill_one_fetch(
/* Decrypt the ilist, and display Dod ID and word position */
for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
fts_node_t* node;
- byte* ptr;
+ const byte* ptr;
ulint decoded = 0;
doc_id_t doc_id = 0;
@@ -3098,13 +3097,10 @@ i_s_fts_index_table_fill_one_fetch(
ptr = node->ilist;
while (decoded < node->ilist_size) {
- ulint pos = fts_decode_vlc(&ptr);
-
- doc_id += pos;
+ doc_id += fts_decode_vlc(&ptr);
/* Get position info */
while (*ptr) {
- pos = fts_decode_vlc(&ptr);
OK(field_store_string(
fields[I_S_FTS_WORD],
@@ -3123,7 +3119,7 @@ i_s_fts_index_table_fill_one_fetch(
longlong(doc_id), true));
OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
- pos, true));
+ fts_decode_vlc(&ptr), true));
OK(schema_table_store_record(
thd, table));
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index 906ece2e557..e45d6fc98f3 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -95,10 +95,6 @@ those defined in mysql file ft_global.h */
/** Threshold where our optimize thread automatically kicks in */
#define FTS_OPTIMIZE_THRESHOLD 10000000
-/** Threshold to avoid exhausting of doc ids. Consecutive doc id difference
-should not exceed FTS_DOC_ID_MAX_STEP */
-#define FTS_DOC_ID_MAX_STEP 65535
-
/** Maximum possible Fulltext word length in bytes (assuming mbmaxlen=4) */
#define FTS_MAX_WORD_LEN (HA_FT_MAXCHARLEN * 4)
diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h
index f5760a16c0e..d49bc7c0254 100644
--- a/storage/innobase/include/fts0types.h
+++ b/storage/innobase/include/fts0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -150,6 +150,9 @@ struct fts_cache_t {
size_t total_size; /*!< total size consumed by the ilist
field of all nodes. SYNC is run
whenever this gets too big */
+ /** total_size at the time of the previous SYNC request */
+ size_t total_size_at_sync;
+
fts_sync_t* sync; /*!< sync structure to sync data to
disk */
ib_alloc_t* sync_heap; /*!< The heap allocator, for indexes
@@ -315,16 +318,6 @@ int fts_doc_id_cmp(
const void* p2); /*!< in: id2 */
/******************************************************************//**
-Decode and return the integer that was encoded using our VLC scheme.*/
-UNIV_INLINE
-ulint
-fts_decode_vlc(
-/*===========*/
- /*!< out: value decoded */
- byte** ptr); /*!< in: ptr to decode from, this ptr is
- incremented by the number of bytes decoded */
-
-/******************************************************************//**
Duplicate a string. */
UNIV_INLINE
void
@@ -339,28 +332,6 @@ fts_string_dup(
mem_heap_t* heap); /*!< in: heap to use */
/******************************************************************//**
-Return length of val if it were encoded using our VLC scheme. */
-UNIV_INLINE
-ulint
-fts_get_encoded_len(
-/*================*/
- /*!< out: length of value
- encoded, in bytes */
- ulint val); /*!< in: value to encode */
-
-/******************************************************************//**
-Encode an integer using our VLC scheme and return the length in bytes. */
-UNIV_INLINE
-ulint
-fts_encode_int(
-/*===========*/
- /*!< out: length of value
- encoded, in bytes */
- ulint val, /*!< in: value to encode */
- byte* buf); /*!< in: buffer, must have
- enough space */
-
-/******************************************************************//**
Get the selected FTS aux INDEX suffix. */
UNIV_INLINE
const char*
@@ -381,6 +352,5 @@ fts_select_index(
ulint len);
#include "fts0types.ic"
-#include "fts0vlc.ic"
#endif /* INNOBASE_FTS0TYPES_H */
diff --git a/storage/innobase/include/fts0vlc.h b/storage/innobase/include/fts0vlc.h
new file mode 100644
index 00000000000..d6e6037777e
--- /dev/null
+++ b/storage/innobase/include/fts0vlc.h
@@ -0,0 +1,124 @@
+/**
+
+Copyright (c) 2021, MariaDB Corporation.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+**/
+/**
+@file include/fts0vlc.h
+Full text variable length integer encoding/decoding.
+
+Created 2021-10-19 Thirunarayanan Balathandayuthapani
+**/
+
+/** Return length of val if it were encoded using our VLC scheme.
+@param val value to encode
+@return length of value encoded, in bytes */
+inline size_t fts_get_encoded_len(doc_id_t val)
+{
+ if (val < static_cast<doc_id_t>(1) << 7)
+ return 1;
+ if (val < static_cast<doc_id_t>(1) << 14)
+ return 2;
+ if (val < static_cast<doc_id_t>(1) << 21)
+ return 3;
+ if (val < static_cast<doc_id_t>(1) << 28)
+ return 4;
+ if (val < static_cast<doc_id_t>(1) << 35)
+ return 5;
+ if (val < static_cast<doc_id_t>(1) << 42)
+ return 6;
+ if (val < static_cast<doc_id_t>(1) << 49)
+ return 7;
+ if (val < static_cast<doc_id_t>(1) << 56)
+ return 8;
+ if (val < static_cast<doc_id_t>(1) << 63)
+ return 9;
+ return 10;
+}
+
+/** Encode an integer using our VLC scheme and return the
+length in bytes.
+@param val value to encode
+@param buf buffer, must have enough space
+@return length of value encoded, in bytes */
+inline byte *fts_encode_int(doc_id_t val, byte *buf)
+{
+ if (val < static_cast<doc_id_t>(1) << 7)
+ goto add_1;
+ if (val < static_cast<doc_id_t>(1) << 14)
+ goto add_2;
+ if (val < static_cast<doc_id_t>(1) << 21)
+ goto add_3;
+ if (val < static_cast<doc_id_t>(1) << 28)
+ goto add_4;
+ if (val < static_cast<doc_id_t>(1) << 35)
+ goto add_5;
+ if (val < static_cast<doc_id_t>(1) << 42)
+ goto add_6;
+ if (val < static_cast<doc_id_t>(1) << 49)
+ goto add_7;
+ if (val < static_cast<doc_id_t>(1) << 56)
+ goto add_8;
+ if (val < static_cast<doc_id_t>(1) << 63)
+ goto add_9;
+
+ *buf++= static_cast<byte>(val >> 63);
+add_9:
+ *buf++= static_cast<byte>(val >> 56) & 0x7F;
+add_8:
+ *buf++= static_cast<byte>(val >> 49) & 0x7F;
+add_7:
+ *buf++= static_cast<byte>(val >> 42) & 0x7F;
+add_6:
+ *buf++= static_cast<byte>(val >> 35) & 0x7F;
+add_5:
+ *buf++= static_cast<byte>(val >> 28) & 0x7F;
+add_4:
+ *buf++= static_cast<byte>(val >> 21) & 0x7F;
+add_3:
+ *buf++= static_cast<byte>(val >> 14) & 0x7F;
+add_2:
+ *buf++= static_cast<byte>(val >> 7) & 0x7F;
+add_1:
+ *buf++= static_cast<byte>(val) | 0x80;
+ return buf;
+}
+
+/** Decode and return the integer that was encoded using
+our VLC scheme.
+@param ptr pointer to decode from, this ptr is
+ incremented by the number of bytes decoded
+@return value decoded */
+inline doc_id_t fts_decode_vlc(const byte **ptr)
+{
+ ut_d(const byte *const start= *ptr);
+ ut_ad(*start);
+
+ doc_id_t val= 0;
+ for (;;)
+ {
+ byte b= *(*ptr)++;
+ val|= (b & 0x7F);
+
+ /* High-bit on means "last byte in the encoded integer". */
+ if (b & 0x80)
+ break;
+ ut_ad(val < static_cast<doc_id_t>(1) << (64 - 7));
+ val <<= 7;
+ }
+
+ ut_ad(*ptr - start <= 10);
+
+ return(val);
+}
diff --git a/storage/innobase/include/fts0vlc.ic b/storage/innobase/include/fts0vlc.ic
deleted file mode 100644
index 75d8535057e..00000000000
--- a/storage/innobase/include/fts0vlc.ic
+++ /dev/null
@@ -1,142 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/******************************************************************//**
-@file include/fts0vlc.ic
-Full text variable length integer encoding/decoding.
-
-Created 2007-03-27 Sunny Bains
-*******************************************************/
-
-#ifndef INNOBASE_FTS0VLC_IC
-#define INNOBASE_FTS0VLC_IC
-
-#include "fts0types.h"
-
-/******************************************************************//**
-Return length of val if it were encoded using our VLC scheme.
-FIXME: We will need to be able encode 8 bytes value
-@return length of value encoded, in bytes */
-UNIV_INLINE
-ulint
-fts_get_encoded_len(
-/*================*/
- ulint val) /* in: value to encode */
-{
- if (val <= 127) {
- return(1);
- } else if (val <= 16383) {
- return(2);
- } else if (val <= 2097151) {
- return(3);
- } else if (val <= 268435455) {
- return(4);
- } else {
- /* Possibly we should care that on 64-bit machines ulint can
- contain values that we can't encode in 5 bytes, but
- fts_encode_int doesn't handle them either so it doesn't much
- matter. */
-
- return(5);
- }
-}
-
-/******************************************************************//**
-Encode an integer using our VLC scheme and return the length in bytes.
-@return length of value encoded, in bytes */
-UNIV_INLINE
-ulint
-fts_encode_int(
-/*===========*/
- ulint val, /* in: value to encode */
- byte* buf) /* in: buffer, must have enough space */
-{
- ulint len;
-
- if (val <= 127) {
- *buf = (byte) val;
-
- len = 1;
- } else if (val <= 16383) {
- *buf++ = (byte)(val >> 7);
- *buf = (byte)(val & 0x7F);
-
- len = 2;
- } else if (val <= 2097151) {
- *buf++ = (byte)(val >> 14);
- *buf++ = (byte)((val >> 7) & 0x7F);
- *buf = (byte)(val & 0x7F);
-
- len = 3;
- } else if (val <= 268435455) {
- *buf++ = (byte)(val >> 21);
- *buf++ = (byte)((val >> 14) & 0x7F);
- *buf++ = (byte)((val >> 7) & 0x7F);
- *buf = (byte)(val & 0x7F);
-
- len = 4;
- } else {
- /* Best to keep the limitations of the 32/64 bit versions
- identical, at least for the time being. */
- ut_ad(val <= 4294967295u);
-
- *buf++ = (byte)(val >> 28);
- *buf++ = (byte)((val >> 21) & 0x7F);
- *buf++ = (byte)((val >> 14) & 0x7F);
- *buf++ = (byte)((val >> 7) & 0x7F);
- *buf = (byte)(val & 0x7F);
-
- len = 5;
- }
-
- /* High-bit on means "last byte in the encoded integer". */
- *buf |= 0x80;
-
- return(len);
-}
-
-/******************************************************************//**
-Decode and return the integer that was encoded using our VLC scheme.
-@return value decoded */
-UNIV_INLINE
-ulint
-fts_decode_vlc(
-/*===========*/
- byte** ptr) /* in: ptr to decode from, this ptr is
- incremented by the number of bytes decoded */
-{
- ulint val = 0;
-
- for (;;) {
- byte b = **ptr;
-
- ++*ptr;
- val |= (b & 0x7F);
-
- /* High-bit on means "last byte in the encoded integer". */
- if (b & 0x80) {
- break;
- } else {
- val <<= 7;
- }
- }
-
- return(val);
-}
-
-#endif
diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h
index 88317a73048..4f4c9a4b596 100644
--- a/storage/innobase/include/mach0data.h
+++ b/storage/innobase/include/mach0data.h
@@ -296,6 +296,28 @@ mach_read_from_n_little_endian(
const byte* buf, /*!< in: from where to read */
ulint buf_size) /*!< in: from how many bytes to read */
MY_ATTRIBUTE((warn_unused_result));
+
+
+/** Reads a 64 bit stored in big endian format
+@param buf From where to read
+@return uint64_t */
+UNIV_INLINE
+uint64_t
+mach_read_uint64_little_endian(const byte* buf)
+{
+#ifdef WORDS_BIGENDIAN
+ return
+ uint64_t(buf[0]) | uint64_t(buf[1]) << 8 |
+ uint64_t(buf[2]) << 16 | uint64_t(buf[3]) << 24 |
+ uint64_t(buf[4]) << 32 | uint64_t(buf[5]) << 40 |
+ uint64_t(buf[6]) << 48 | uint64_t(buf[7]) << 56;
+#else
+ uint64_t n;
+ memcpy(&n, buf, sizeof(uint64_t));
+ return n;
+#endif
+}
+
/*********************************************************//**
Writes a ulint in the little-endian format. */
UNIV_INLINE
diff --git a/storage/innobase/include/ut0wqueue.h b/storage/innobase/include/ut0wqueue.h
index 347622989dd..26838c95443 100644
--- a/storage/innobase/include/ut0wqueue.h
+++ b/storage/innobase/include/ut0wqueue.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -46,6 +46,8 @@ struct ib_wqueue_t
ib_mutex_t mutex;
/** Work item list */
ib_list_t* items;
+ /** ib_list_len(*items) */
+ size_t length;
};
/****************************************************************//**
@@ -83,12 +85,5 @@ void*
ib_wqueue_nowait(
/*=============*/
ib_wqueue_t* wq); /*<! in: work queue */
-/********************************************************************
-Get number of items on queue.
-@return number of items on queue */
-ulint
-ib_wqueue_len(
-/*==========*/
- ib_wqueue_t* wq); /*<! in: work queue */
#endif /* IB_WORK_QUEUE_H */
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index ea71c59c344..360a5e35fa4 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1457,23 +1457,6 @@ error_exit:
trx->error_state = DB_FTS_INVALID_DOCID;
goto error_exit;
}
-
- /* Difference between Doc IDs are restricted within
- 4 bytes integer. See fts_get_encoded_len(). Consecutive
- doc_ids difference should not exceed
- FTS_DOC_ID_MAX_STEP value. */
-
- if (doc_id - next_doc_id >= FTS_DOC_ID_MAX_STEP) {
- ib::error() << "Doc ID " << doc_id
- << " is too big. Its difference with"
- " largest used Doc ID "
- << next_doc_id - 1 << " cannot"
- " exceed or equal to "
- << FTS_DOC_ID_MAX_STEP;
- err = DB_FTS_INVALID_DOCID;
- trx->error_state = DB_FTS_INVALID_DOCID;
- goto error_exit;
- }
}
if (table->skip_alter_undo) {
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 16ea7c41d71..ffb514a97c4 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1349,14 +1349,6 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
ut_ad(!rsegs.m_redo.undo);
ut_ad(UT_LIST_GET_LEN(lock.evicted_tables) == 0);
- if (trx_rseg_t *rseg= rsegs.m_redo.rseg)
- {
- mutex_enter(&rseg->mutex);
- ut_ad(rseg->trx_ref_count > 0);
- --rseg->trx_ref_count;
- mutex_exit(&rseg->mutex);
- }
-
if (mtr)
{
if (trx_undo_t *&undo= rsegs.m_noredo.undo)
@@ -1405,6 +1397,16 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
ut_ad(!rsegs.m_noredo.undo);
+ /* Only after trx_undo_commit_cleanup() it is safe to release
+ our rseg reference. */
+ if (trx_rseg_t *rseg= rsegs.m_redo.rseg)
+ {
+ mutex_enter(&rseg->mutex);
+ ut_ad(rseg->trx_ref_count > 0);
+ --rseg->trx_ref_count;
+ mutex_exit(&rseg->mutex);
+ }
+
/* Free all savepoints, starting from the first. */
trx_named_savept_t *savep= UT_LIST_GET_FIRST(trx_savepoints);
diff --git a/storage/innobase/unittest/CMakeLists.txt b/storage/innobase/unittest/CMakeLists.txt
new file mode 100644
index 00000000000..df98cddf73e
--- /dev/null
+++ b/storage/innobase/unittest/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright (c) 2021, MariaDB Corporation.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_SOURCE_DIR}/unittest/mytap
+ ${CMAKE_SOURCE_DIR}/storage/innobase/include)
+ADD_EXECUTABLE(innodb_fts-t innodb_fts-t.cc)
+TARGET_LINK_LIBRARIES(innodb_fts-t mysys mytap)
+ADD_DEPENDENCIES(innodb_fts-t GenError)
+MY_ADD_TEST(innodb_fts)
diff --git a/storage/innobase/unittest/innodb_fts-t.cc b/storage/innobase/unittest/innodb_fts-t.cc
new file mode 100644
index 00000000000..4e10c0e439e
--- /dev/null
+++ b/storage/innobase/unittest/innodb_fts-t.cc
@@ -0,0 +1,52 @@
+#include "tap.h"
+#include "fts0fts.h"
+#include "fts0vlc.h"
+
+struct fts_encode_info
+{
+ const byte buf[10];
+ size_t len;
+ doc_id_t val;
+};
+
+/* Contains fts encoding min & max value for each length bytes */
+static const fts_encode_info fts_info[]=
+{
+ {{0x80}, 1, 0},
+ {{0xFF}, 1, (1 << 7) - 1},
+ {{0x01, 0x80}, 2, 1 << 7},
+ {{0x7F, 0XFF}, 2, (1 << 14) - 1},
+ {{0x01, 0x00, 0x80}, 3, 1 << 14},
+ {{0x7F, 0X7F, 0XFF}, 3, (1 << 21) - 1},
+ {{0x01, 0x00, 0x00, 0x80}, 4, 1 << 21},
+ {{0x7F, 0X7F, 0X7F, 0xFF}, 4, (1 << 28) - 1},
+ {{0x01, 0x00, 0x00, 0x00, 0x80}, 5, 1 << 28},
+ {{0x7F, 0X7F, 0X7F, 0x7F, 0xFF}, 5, (1ULL << 35) - 1},
+ {{0x01, 0x00, 0x00, 0x00, 0x00, 0x80}, 6, 1ULL << 35},
+ {{0x7F, 0X7F, 0X7F, 0x7F, 0x7F, 0xFF}, 6, (1ULL << 42) - 1},
+ {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, 7, 1ULL << 42},
+ {{0x7F, 0X7F, 0X7F, 0x7F, 0x7F, 0x7F, 0XFF}, 7, (1ULL << 49) - 1},
+ {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, 8, 1ULL << 49},
+ {{0x7F, 0X7F, 0X7F, 0x7F, 0x7F, 0x7F, 0X7F, 0XFF}, 8, (1ULL << 56) -1},
+ {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, 9, 1ULL << 56},
+ {{0x7F, 0X7F, 0X7F, 0x7F, 0x7F, 0x7F, 0X7F, 0x7F, 0XFF}, 9, (1ULL << 63) -1},
+ {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, 10, 1ULL << 63},
+ {{0x01, 0X7F, 0X7F, 0x7F, 0x7F, 0x7F, 0X7F, 0x7F, 0x7F, 0xFF}, 10, ~0ULL}
+};
+
+int main(int, char**)
+{
+ for (int i= array_elements(fts_info); i--;)
+ {
+ byte buf[10];
+ const byte* fts_buf= buf;
+ size_t len= fts_encode_int(fts_info[i].val, buf) - &buf[0];
+ if (fts_info[i].len == len &&
+ !memcmp(&fts_info[i].buf, buf, len) &&
+ fts_decode_vlc(&fts_buf) == fts_info[i].val &&
+ fts_buf == &buf[len])
+ ok(true, "FTS Encoded for %d bytes", fts_info[i].len);
+ else
+ ok(false, "FTS Encoded for %d bytes", fts_info[i].len);
+ }
+}
diff --git a/storage/innobase/ut/ut0wqueue.cc b/storage/innobase/ut/ut0wqueue.cc
index 53bb0c8b148..af56bb5cba0 100644
--- a/storage/innobase/ut/ut0wqueue.cc
+++ b/storage/innobase/ut/ut0wqueue.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2019, 2020, MariaDB Corporation.
+Copyright (c) 2019, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -44,6 +44,7 @@ ib_wqueue_create(void)
mutex_create(LATCH_ID_WORK_QUEUE, &wq->mutex);
wq->items = ib_list_create();
+ wq->length = 0;
return(wq);
}
@@ -74,6 +75,8 @@ ib_wqueue_add(ib_wqueue_t* wq, void* item, mem_heap_t* heap, bool wq_locked)
}
ib_list_add_last(wq->items, item, heap);
+ wq->length++;
+ ut_ad(wq->length == ib_list_len(wq->items));
if (!wq_locked) {
mutex_exit(&wq->mutex);
@@ -97,6 +100,8 @@ ib_wqueue_nowait(
if (node) {
ib_list_remove(wq->items, node);
+ --wq->length;
+ ut_ad(wq->length == ib_list_len(wq->items));
}
}
@@ -114,20 +119,3 @@ bool ib_wqueue_is_empty(ib_wqueue_t* wq)
mutex_exit(&wq->mutex);
return is_empty;
}
-
-/********************************************************************
-Get number of items on queue.
-@return number of items on queue */
-ulint
-ib_wqueue_len(
-/*==========*/
- ib_wqueue_t* wq) /*<! in: work queue */
-{
- ulint len = 0;
-
- mutex_enter(&wq->mutex);
- len = ib_list_len(wq->items);
- mutex_exit(&wq->mutex);
-
- return(len);
-}
diff --git a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt
index 8c71563f722..4f076458a36 100644
--- a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt
@@ -89,7 +89,12 @@ else()
endif()
set_target_properties(libgroonga PROPERTIES OUTPUT_NAME "groonga")
+if (HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ set(ATOMIC_LIBS atomic)
+endif()
+
set(GRN_ALL_LIBRARIES
+ ${ATOMIC_LIBS}
${EXECINFO_LIBS}
${RT_LIBS}
${PTHREAD_LIBS}