From fdc4b7a6b222ffdcbe355255b40e500d339fbf3b Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 15 Dec 2020 16:28:42 +0530 Subject: [PATCH 01/18] MDEV-21478 Inplace ALTER fails to report error when FTS_DOC_ID with wrong data type is added Inplace alter fails to report error when fts_doc_id column with wrong data type is added. prepare_inplace_alter_table_dict(): Should check whether the column is fts_doc_id. It should be of bigint type, should accept non null data type and it should be in capital letters. --- .../suite/innodb_fts/r/innodb-fts-ddl.result | 32 +++++++++++++++ .../suite/innodb_fts/t/innodb-fts-ddl.test | 41 +++++++++++++++++++ storage/innobase/handler/handler0alter.cc | 17 ++++++++ 3 files changed, 90 insertions(+) diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result index f23813aed48..f1e625037f3 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result @@ -234,3 +234,35 @@ CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY, f1 VARCHAR(200),FULLTEXT fidx(f1))engine=innodb; ALTER TABLE t1 DROP index fidx, ADD FULLTEXT INDEX(f1); DROP TABLE t1; +# +# MDEV-21478 Inplace alter fails to report error when +# FTS_DOC_ID is added +SET NAMES utf8; +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +ALTER TABLE t1 ADD FTS_DOC_ıD BIGINT UNSIGNED NOT NULL, ALGORITHM=COPY; +ALTER TABLE t1 DROP COLUMN FTS_DOC_ıD; +ALTER TABLE t1 ADD FTS_DOC_ıD BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT NOT NULL)ENGINE=InnoDB; +ALTER TABLE t1 ADD FTS_DOC_İD BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE; +ERROR 42000: Incorrect column name 'FTS_DOC_İD' +ALTER TABLE t1 ADD FTS_DOC_İD BIGINT UNSIGNED NOT NULL, ALGORITHM=COPY; +ERROR 42000: Incorrect column name 'FTS_DOC_İD' +ALTER TABLE t1 ADD fts_doc_id INT, ALGORITHM=COPY; +ERROR 42000: Incorrect column name 'fts_doc_id' +ALTER TABLE t1 ADD fts_doc_id INT, ALGORITHM=INPLACE; +ERROR 42000: Incorrect column name 'fts_doc_id' +ALTER TABLE t1 ADD fts_doc_id BIGINT UNSIGNED NOT NULL, ALGORITHM=COPY; +ERROR 42000: Incorrect column name 'fts_doc_id' +ALTER TABLE t1 ADD fts_doc_id BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE; +ERROR 42000: Incorrect column name 'fts_doc_id' +ALTER TABLE t1 ADD FTS_DOC_ID INT UNSIGNED NOT NULL, ALGORITHM=COPY; +ERROR 42000: Incorrect column name 'FTS_DOC_ID' +ALTER TABLE t1 ADD FTS_DOC_ID INT UNSIGNED NOT NULL, ALGORITHM=INPLACE; +ERROR 42000: Incorrect column name 'FTS_DOC_ID' +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test index cd292803fb3..e055acc4968 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test @@ -278,3 +278,44 @@ CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY, f1 VARCHAR(200),FULLTEXT fidx(f1))engine=innodb; ALTER TABLE t1 DROP index fidx, ADD FULLTEXT INDEX(f1); DROP TABLE t1; + +--echo # +--echo # MDEV-21478 Inplace alter fails to report error when +--echo # FTS_DOC_ID is added + +SET NAMES utf8; + +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +ALTER TABLE t1 ADD FTS_DOC_ıD BIGINT UNSIGNED NOT NULL, ALGORITHM=COPY; +ALTER TABLE t1 DROP COLUMN FTS_DOC_ıD; +ALTER TABLE t1 ADD FTS_DOC_ıD BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE; +DROP TABLE t1; + +CREATE TABLE t1 (f1 INT NOT NULL)ENGINE=InnoDB; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD FTS_DOC_İD BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD FTS_DOC_İD BIGINT UNSIGNED NOT NULL, ALGORITHM=COPY; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD fts_doc_id INT, ALGORITHM=COPY; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD fts_doc_id INT, ALGORITHM=INPLACE; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD fts_doc_id BIGINT UNSIGNED NOT NULL, ALGORITHM=COPY; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD fts_doc_id BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD FTS_DOC_ID INT UNSIGNED NOT NULL, ALGORITHM=COPY; + +--error ER_WRONG_COLUMN_NAME +ALTER TABLE t1 ADD FTS_DOC_ID INT UNSIGNED NOT NULL, ALGORITHM=INPLACE; + +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 0bd11d74b09..7655b93e736 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4663,6 +4663,23 @@ prepare_inplace_alter_table_dict( goto new_clustered_failed; } + /** Note the FTS_DOC_ID name is case sensitive due + to internal query parser. + FTS_DOC_ID column must be of BIGINT NOT NULL type + and it should be in all capitalized characters */ + if (!innobase_strcasecmp(field->field_name, + FTS_DOC_ID_COL_NAME)) { + if (col_type != DATA_INT + || field->real_maybe_null() + || col_len != sizeof(doc_id_t) + || strcmp(field->field_name, + FTS_DOC_ID_COL_NAME)) { + my_error(ER_WRONG_COLUMN_NAME, MYF(0), + field->field_name); + goto new_clustered_failed; + } + } + if (is_virtual) { dict_mem_table_add_v_col( ctx->new_table, ctx->heap, From 1be707286ef13041a67e6e6ca30125470245a898 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 12 Jan 2021 11:38:26 +0530 Subject: [PATCH 02/18] Added the test case for MDEV-23804 --- mysql-test/main/derived_cond_pushdown.result | 70 ++++++++++++++++++++ mysql-test/main/derived_cond_pushdown.test | 13 ++++ 2 files changed, 83 insertions(+) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 1be7897d3af..27ffffd7581 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -17064,4 +17064,74 @@ id 2 3 DROP TABLE t; +# +# MDEV-23804: Server crashes in st_select_lex::collect_grouping_fields_for_derived +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (3),(4); +CREATE VIEW v1 AS SELECT a FROM t1 UNION VALUES (3),(4); +ANALYZE FORMAT=JSON SELECT * from v1 WHERE a=3; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 50, + "attached_condition": "v1.a = 3", + "materialized": { + "query_block": { + "union_result": { + "table_name": "", + "access_type": "ALL", + "r_loops": 1, + "r_rows": 2, + "query_specifications": [ + { + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 50, + "attached_condition": "t1.a = 3" + } + } + }, + { + "query_block": { + "select_id": 3, + "operation": "UNION", + "table": { + "message": "No tables used" + } + } + } + ] + } + } + } + } + } +} +SELECT * from v1 WHERE a=3; +a +3 +DROP VIEW v1; +DROP TABLE t1; # End of 10.3 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 1b980fd3685..12d34a8326a 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -3466,4 +3466,17 @@ eval set statement optimizer_switch='split_materialized=on' for $q; DROP TABLE t; +--echo # +--echo # MDEV-23804: Server crashes in st_select_lex::collect_grouping_fields_for_derived +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (3),(4); +CREATE VIEW v1 AS SELECT a FROM t1 UNION VALUES (3),(4); +--source include/analyze-format.inc +ANALYZE FORMAT=JSON SELECT * from v1 WHERE a=3; +SELECT * from v1 WHERE a=3; +DROP VIEW v1; +DROP TABLE t1; + --echo # End of 10.3 tests From 69c86abb646361c607a248f079f8fd4e600dcada Mon Sep 17 00:00:00 2001 From: Kentoku SHIBA Date: Wed, 15 Apr 2020 23:19:10 +0900 Subject: [PATCH 03/18] MDEV-20502 Queries against spider tables return wrong values for columns following constant declarations. When executing a query like "select id, 0 as const, val from ...", there are 3 columns(items) in Query->select at handlerton->create_group_by(). After that, MariaDB makes a temporary table with 2 columns. The skipped items are const item, so fixing Spider to skip const items for items at Query->select. --- .../bugfix/include/mdev_20502_deinit.inc | 11 +++ .../spider/bugfix/include/mdev_20502_init.inc | 25 +++++++ .../spider/bugfix/r/mdev_20502.result | 61 ++++++++++++++++ .../mysql-test/spider/bugfix/t/mdev_20502.cnf | 3 + .../spider/bugfix/t/mdev_20502.test | 71 +++++++++++++++++++ .../mysql-test/spider/r/timestamp.result | 2 +- storage/spider/spd_db_conn.cc | 3 + storage/spider/spd_db_mysql.cc | 20 +++++- storage/spider/spd_db_oracle.cc | 19 ++++- storage/spider/spd_group_by_handler.cc | 5 ++ 10 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/include/mdev_20502_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/mdev_20502_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_20502.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test diff --git a/storage/spider/mysql-test/spider/bugfix/include/mdev_20502_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/mdev_20502_deinit.inc new file mode 100644 index 00000000000..76b7582abfe --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/mdev_20502_deinit.inc @@ -0,0 +1,11 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/mdev_20502_init.inc b/storage/spider/mysql-test/spider/bugfix/include/mdev_20502_init.inc new file mode 100644 index 00000000000..fd8cc0d8170 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/mdev_20502_init.inc @@ -0,0 +1,25 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + val int(10) unsigned DEFAULT NULL, + PRIMARY KEY (id) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT id, val FROM tbl_a ORDER BY id; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result new file mode 100644 index 00000000000..284f62e522e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result @@ -0,0 +1,61 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +this test is for MDEV-20502 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +val int(10) unsigned DEFAULT NULL, +PRIMARY KEY(id) +) ENGINE=Spider COMMENT='table "tbl_a", srv "s_2_1"' +INSERT INTO tbl_a (val) VALUES (1); + +test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT id, 0 AS const, val FROM tbl_a; +id const val +1 0 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`id` `id`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT id, val FROM tbl_a ORDER BY id; +id val +1 1 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test new file mode 100644 index 00000000000..4693f2f7409 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test @@ -0,0 +1,71 @@ +--source ../include/mdev_20502_init.inc +--echo +--echo this test is for MDEV-20502 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + val int(10) unsigned DEFAULT NULL, + PRIMARY KEY(id) +) $MASTER_1_ENGINE $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + val int(10) unsigned DEFAULT NULL, + PRIMARY KEY(id) +) $MASTER_1_ENGINE $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a (val) VALUES (1); + +--echo +--echo test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT id, 0 AS const, val FROM tbl_a; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/mdev_20502_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/r/timestamp.result b/storage/spider/mysql-test/spider/r/timestamp.result index bd1f442d462..4e4badccc41 100644 --- a/storage/spider/mysql-test/spider/r/timestamp.result +++ b/storage/spider/mysql-test/spider/r/timestamp.result @@ -396,7 +396,7 @@ select t0.`col_d` `col_d`,t0.`col_t` `col_t` from `ts_test_remote`.`tbl_f` t0 select (timestamp(t0.`col_d` , t0.`col_t`)) `TIMESTAMP(col_d, col_t)` from `ts_test_remote`.`tbl_f` t0 select (timestamp('2018-06-25' , t0.`col_t`)) `TIMESTAMP('2018-06-25', col_t)` from `ts_test_remote`.`tbl_f` t0 select (timestamp(t0.`col_d` , '10:43:21')) `TIMESTAMP(col_d, '10:43:21')` from `ts_test_remote`.`tbl_f` t0 -select (timestamp('2018-06-25' , '10:43:21')) `TIMESTAMP('2018-06-25', '10:43:21')` from `ts_test_remote`.`tbl_f` t0 +select 1 from `ts_test_remote`.`tbl_f` t0 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT col_d, col_t FROM tbl_f; col_d col_t diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index e87321f896d..cea85b46657 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -3013,6 +3013,9 @@ int spider_db_fetch_table( #ifndef DBUG_OFF dbug_tmp_restore_column_map(table->write_set, tmp_map); #endif + } else { + DBUG_PRINT("info", ("spider bitmap is not set %s", + SPIDER_field_name_str(*field))); } row->next(); } diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 128cd494e7f..cac6b063ad0 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -14277,15 +14277,21 @@ int spider_mbase_handler::append_list_item_select( spider_fields *fields ) { int error_num; - uint32 length; + uint32 length, begin; List_iterator_fast it(*select); Item *item; Field *field; const char *item_name; DBUG_ENTER("spider_mbase_handler::append_list_item_select"); DBUG_PRINT("info",("spider this=%p", this)); + begin = str->length(); while ((item = it++)) { + if (item->const_item()) + { + DBUG_PRINT("info",("spider const item")); + continue; + } if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { @@ -14313,7 +14319,17 @@ int spider_mbase_handler::append_list_item_select( } str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - str->length(str->length() - SPIDER_SQL_COMMA_LEN); + if (begin == str->length()) + { + /* no columns */ + if (str->reserve(SPIDER_SQL_ONE_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_ONE_STR, SPIDER_SQL_ONE_LEN); + } else { + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + } DBUG_RETURN(0); } diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index d3147c19f2f..b7e8100e480 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -12739,14 +12739,21 @@ int spider_oracle_handler::append_list_item_select( ) { int error_num; uint dbton_id = spider_dbton_oracle.dbton_id, length; + uint32 begin; List_iterator_fast it(*select); Item *item; Field *field; const char *item_name; DBUG_ENTER("spider_oracle_handler::append_list_item_select"); DBUG_PRINT("info",("spider this=%p", this)); + begin = str->length(); while ((item = it++)) { + if (item->const_item()) + { + DBUG_PRINT("info",("spider const item")); + continue; + } if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { @@ -12774,7 +12781,17 @@ int spider_oracle_handler::append_list_item_select( } str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - str->length(str->length() - SPIDER_SQL_COMMA_LEN); + if (begin == str->length()) + { + /* no columns */ + if (str->reserve(SPIDER_SQL_ONE_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_ONE_STR, SPIDER_SQL_ONE_LEN); + } else { + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + } DBUG_RETURN(0); } diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index c83ee753e5b..8bd0eca507f 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -1794,6 +1794,11 @@ group_by_handler *spider_create_group_by_handler( while ((item = it++)) { DBUG_PRINT("info",("spider select item=%p", item)); + if (item->const_item()) + { + DBUG_PRINT("info",("spider const item")); + continue; + } if (spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0, roop_count, TRUE, fields_arg)) { From de5e5ab2106fe37b857eed424f12d197d2c32082 Mon Sep 17 00:00:00 2001 From: Kentoku SHIBA Date: Tue, 5 May 2020 22:41:10 +0900 Subject: [PATCH 04/18] MDEV-20502 Queries against spider tables return wrong values for columns following constant declarations. Add test cases. --- .../spider/bugfix/r/mdev_20502.result | 24 +++++++++++++++++++ .../spider/bugfix/t/mdev_20502.test | 7 ++++++ 2 files changed, 31 insertions(+) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result index 284f62e522e..e5f16b81329 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result @@ -36,14 +36,38 @@ connection master_1; SELECT id, 0 AS const, val FROM tbl_a; id const val 1 0 1 +SELECT 1+2, id, 0 AS const, val, val+10, (SELECT tbl_a.val+1 FROM tbl_a) AS sq +FROM tbl_a; +1+2 id const val val+10 sq +3 1 0 1 11 2 +INSERT INTO tbl_a (val) VALUES (2), (1); +SELECT val+10, 0 AS const, val, (SELECT tbl_a.val+1 FROM tbl_a LIMIT 1) AS sq +FROM tbl_a GROUP BY val; +val+10 const val sq +11 0 1 2 +12 0 2 2 +SELECT MAX(id) AS m, 0 AS const, val, (SELECT tbl_a.val+1 FROM tbl_a LIMIT 1) AS sq +FROM tbl_a GROUP BY val; +m const val sq +3 0 1 2 +2 0 2 2 connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument select t0.`id` `id`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 +select t0.`id` `id`,t0.`val` `val`,(t0.`val` + 10) `val+10` from `auto_test_remote`.`tbl_a` t0 +select (t0.`val` + 1) `tbl_a.val+1` from `auto_test_remote`.`tbl_a` t0 +select `id`,`val` from `auto_test_remote`.`tbl_a` order by `id` desc limit 1 for update +select (t0.`val` + 10) `val+10`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 group by t0.`val` order by t0.`val` +select (t0.`val` + 1) `tbl_a.val+1` from `auto_test_remote`.`tbl_a` t0 limit 1 +select max(t0.`id`) `m`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 group by t0.`val` order by t0.`val` +select (t0.`val` + 1) `tbl_a.val+1` from `auto_test_remote`.`tbl_a` t0 limit 1 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT id, val FROM tbl_a ORDER BY id; id val 1 1 +2 2 +3 1 deinit connection master_1; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test index 4693f2f7409..2d6ff5b4663 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_20502.test @@ -49,6 +49,13 @@ TRUNCATE TABLE mysql.general_log; --connection master_1 SELECT id, 0 AS const, val FROM tbl_a; +SELECT 1+2, id, 0 AS const, val, val+10, (SELECT tbl_a.val+1 FROM tbl_a) AS sq +FROM tbl_a; +INSERT INTO tbl_a (val) VALUES (2), (1); +SELECT val+10, 0 AS const, val, (SELECT tbl_a.val+1 FROM tbl_a LIMIT 1) AS sq +FROM tbl_a GROUP BY val; +SELECT MAX(id) AS m, 0 AS const, val, (SELECT tbl_a.val+1 FROM tbl_a LIMIT 1) AS sq +FROM tbl_a GROUP BY val; --connection child2_1 eval $CHILD2_1_SELECT_ARGUMENT1; From f7ff8f5dd9e99aa480bc7d56dff1a2a642f12b77 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Jan 2021 12:35:52 +0100 Subject: [PATCH 05/18] MDEV-24524 Assertion `ls->length < 0xFFFFFFFFL && ((ls->length == 0 && !ls->str) || ls->length == strlen(ls->str))' failed in String::append on SELECT from I_S don't expect return type of a stored function to be valid. it's read from a table, so can be messed with. it even can contain \0 bytes in the middle of the type name --- mysql-test/main/sp-ucs2.result | 8 +++++++- mysql-test/main/sp-ucs2.test | 14 +++++++++++--- sql/sp.cc | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/sp-ucs2.result b/mysql-test/main/sp-ucs2.result index ca448efa535..0f5624314d7 100644 --- a/mysql-test/main/sp-ucs2.result +++ b/mysql-test/main/sp-ucs2.result @@ -115,7 +115,6 @@ RETURN 'str'; END| ERROR 42000: COLLATION 'ucs2_unicode_ci' is not valid for CHARACTER SET 'latin1' SET NAMES utf8; -DROP FUNCTION IF EXISTS bug48766; CREATE FUNCTION bug48766 () RETURNS ENUM( 'w' ) CHARACTER SET ucs2 RETURN 0; @@ -140,3 +139,10 @@ WHERE ROUTINE_NAME='bug48766'; DTD_IDENTIFIER enum('а','б','в','г') DROP FUNCTION bug48766; +call mtr.add_suppression('invalid value in column mysql.proc.'); +set collation_connection=ucs2_general_ci; +insert into mysql.proc (db, name, type, specific_name, language, sql_data_access, is_deterministic, security_type, param_list, returns, body, definer, created, modified, sql_mode, comment, character_set_client, collation_connection, db_collation, body_utf8 ) values ( 'a', 'a', 'function', 'bug14233_1', 'sql', 'reads_sql_data', 'no', 'definer', '', 'int(10)', 'select * from mysql.user', 'root@localhost', now(), '0000-00-00 00:00:00', '', '', '', '', '', 'select * from mysql.user' ); +select * from information_schema.routines where routine_name='a'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 +set collation_connection=default; +delete from mysql.proc where name='a'; diff --git a/mysql-test/main/sp-ucs2.test b/mysql-test/main/sp-ucs2.test index a1aec8071b4..004d62f4cc5 100644 --- a/mysql-test/main/sp-ucs2.test +++ b/mysql-test/main/sp-ucs2.test @@ -151,9 +151,6 @@ delimiter ;| # Bug#48766 SHOW CREATE FUNCTION returns extra data in return clause # SET NAMES utf8; ---disable_warnings -DROP FUNCTION IF EXISTS bug48766; ---enable_warnings # # Test that Latin letters are not prepended with extra '\0'. # @@ -175,3 +172,14 @@ SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME='bug48766'; DROP FUNCTION bug48766; + +# +# +# +call mtr.add_suppression('invalid value in column mysql.proc.'); +set collation_connection=ucs2_general_ci; +insert into mysql.proc (db, name, type, specific_name, language, sql_data_access, is_deterministic, security_type, param_list, returns, body, definer, created, modified, sql_mode, comment, character_set_client, collation_connection, db_collation, body_utf8 ) values ( 'a', 'a', 'function', 'bug14233_1', 'sql', 'reads_sql_data', 'no', 'definer', '', 'int(10)', 'select * from mysql.user', 'root@localhost', now(), '0000-00-00 00:00:00', '', '', '', '', '', 'select * from mysql.user' ); +--error ER_PARSE_ERROR +select * from information_schema.routines where routine_name='a'; +set collation_connection=default; +delete from mysql.proc where name='a'; diff --git a/sql/sp.cc b/sql/sp.cc index 98e94ac06cf..a4c4ca58414 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2948,7 +2948,7 @@ Sp_handler::show_create_sp(THD *thd, String *buf, buf->append(STRING_WITH_LEN(" RETURN ")); else buf->append(STRING_WITH_LEN(" RETURNS ")); - buf->append(&returns); + buf->append(returns.str, returns.length); // Not \0 terminated } buf->append('\n'); switch (chistics.daccess) { From d463677f7e4226e15ec3814860164cf4c7229e5f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Jan 2021 15:39:36 +0100 Subject: [PATCH 06/18] failing to parse an SP should not abort information_schema.routines --- mysql-test/main/sp-ucs2.result | 7 +++++-- mysql-test/main/sp-ucs2.test | 3 +-- sql/sql_show.cc | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/sp-ucs2.result b/mysql-test/main/sp-ucs2.result index 0f5624314d7..389fa946ad5 100644 --- a/mysql-test/main/sp-ucs2.result +++ b/mysql-test/main/sp-ucs2.result @@ -142,7 +142,10 @@ DROP FUNCTION bug48766; call mtr.add_suppression('invalid value in column mysql.proc.'); set collation_connection=ucs2_general_ci; insert into mysql.proc (db, name, type, specific_name, language, sql_data_access, is_deterministic, security_type, param_list, returns, body, definer, created, modified, sql_mode, comment, character_set_client, collation_connection, db_collation, body_utf8 ) values ( 'a', 'a', 'function', 'bug14233_1', 'sql', 'reads_sql_data', 'no', 'definer', '', 'int(10)', 'select * from mysql.user', 'root@localhost', now(), '0000-00-00 00:00:00', '', '', '', '', '', 'select * from mysql.user' ); -select * from information_schema.routines where routine_name='a'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 +select routine_name from information_schema.routines where routine_name='a'; +routine_name +a +Warnings: +Warning 1601 Creation context of stored routine `a`.`a` is invalid set collation_connection=default; delete from mysql.proc where name='a'; diff --git a/mysql-test/main/sp-ucs2.test b/mysql-test/main/sp-ucs2.test index 004d62f4cc5..3276da3e257 100644 --- a/mysql-test/main/sp-ucs2.test +++ b/mysql-test/main/sp-ucs2.test @@ -179,7 +179,6 @@ DROP FUNCTION bug48766; call mtr.add_suppression('invalid value in column mysql.proc.'); set collation_connection=ucs2_general_ci; insert into mysql.proc (db, name, type, specific_name, language, sql_data_access, is_deterministic, security_type, param_list, returns, body, definer, created, modified, sql_mode, comment, character_set_client, collation_connection, db_collation, body_utf8 ) values ( 'a', 'a', 'function', 'bug14233_1', 'sql', 'reads_sql_data', 'no', 'definer', '', 'int(10)', 'select * from mysql.user', 'root@localhost', now(), '0000-00-00 00:00:00', '', '', '', '', '', 'select * from mysql.user' ); ---error ER_PARSE_ERROR -select * from information_schema.routines where routine_name='a'; +select routine_name from information_schema.routines where routine_name='a'; set collation_connection=default; delete from mysql.proc where name='a'; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index aef07fa4425..f25a8861bc1 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5059,7 +5059,8 @@ public: Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { - if (sql_errno == ER_TRG_NO_DEFINER || sql_errno == ER_TRG_NO_CREATION_CTX) + if (sql_errno == ER_TRG_NO_DEFINER || sql_errno == ER_TRG_NO_CREATION_CTX + || sql_errno == ER_PARSE_ERROR) return true; if (*level != Sql_condition::WARN_LEVEL_ERROR) From 83bbe36831e11adb8253132b5715b4b843e9bf09 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Jan 2021 23:59:00 +0100 Subject: [PATCH 07/18] fix sporadic failures of main.processlist_notembedded the test was doing --replace_result $con_id con_id eval SHOW EXPLAIN FOR $con_id; with the intention of replacing the variable part of the statement in the result log. But actually replace_result replaces everything that matches. In particular, when $con_id is 100, the warning Note 1003 select sleep(100000) becomes Note con_id3 select sleep(con_id000) --- .../main/processlist_notembedded.result | 16 +++++++++------ mysql-test/main/processlist_notembedded.test | 20 +++++++++---------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/mysql-test/main/processlist_notembedded.result b/mysql-test/main/processlist_notembedded.result index ddde45f3031..26ca4ef8d0d 100644 --- a/mysql-test/main/processlist_notembedded.result +++ b/mysql-test/main/processlist_notembedded.result @@ -1,7 +1,7 @@ # # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes # -connect con1,localhost,root,,; +connect con1,localhost,root; connection con1; SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync WAIT_FOR go'; connection default; @@ -13,17 +13,21 @@ user disconnect con1; connection default; SET DEBUG_SYNC = 'RESET'; -End of 5.5 tests +# +# End of 5.5 tests +# # # MDEV-23752: SHOW EXPLAIN FOR thd waits for sleep # -connect con1,localhost,root,,; -select sleep(100000);; +connect con1,localhost,root; +select sleep(100000); connection default; -SHOW EXPLAIN FOR con_id; +SHOW EXPLAIN FOR $con_id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select sleep(100000) -KILL QUERY con_id; +KILL QUERY $con_id; +# # End of 10.2 tests +# diff --git a/mysql-test/main/processlist_notembedded.test b/mysql-test/main/processlist_notembedded.test index 26021040c39..cc577200368 100644 --- a/mysql-test/main/processlist_notembedded.test +++ b/mysql-test/main/processlist_notembedded.test @@ -7,7 +7,7 @@ source include/count_sessions.inc; --echo # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes --echo # -connect (con1,localhost,root,,); +connect con1,localhost,root; connection con1; @@ -39,22 +39,22 @@ SET DEBUG_SYNC = 'RESET'; source include/wait_until_count_sessions.inc; ---echo End of 5.5 tests +--echo # +--echo # End of 5.5 tests +--echo # --echo # --echo # MDEV-23752: SHOW EXPLAIN FOR thd waits for sleep --echo # ---connect (con1,localhost,root,,) +--connect con1,localhost,root --let $con_id = `SELECT CONNECTION_ID()` ---send select sleep(100000); +--send select sleep(100000) --connection default +evalp SHOW EXPLAIN FOR $con_id; +evalp KILL QUERY $con_id; ---replace_result $con_id con_id -eval SHOW EXPLAIN FOR $con_id; - ---replace_result $con_id con_id -eval KILL QUERY $con_id; - +--echo # --echo # End of 10.2 tests +--echo # From f144ce2cfa086182fbd2b44408c70bd3456408f2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 5 Jan 2021 11:42:34 +0100 Subject: [PATCH 08/18] MDEV-20763 Table corruption or Assertion `btr_validate_index(index, 0, false)' failed in row_upd_sec_index_entry with virtual column and EMPTY_STRING_IS_NULL SQL mode unset empty_string_is_null mode when parsing generated columns in a table, this mode affects pasring. --- mysql-test/main/empty_string_literal.result | 29 +++++++++++++++++++++ mysql-test/main/empty_string_literal.test | 19 ++++++++++++++ sql/table.cc | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/empty_string_literal.result b/mysql-test/main/empty_string_literal.result index 2ca491a7dd8..bbcf27cf993 100644 --- a/mysql-test/main/empty_string_literal.result +++ b/mysql-test/main/empty_string_literal.result @@ -179,3 +179,32 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select NULL AS `NULL` +# +# MDEV-20763 Table corruption or Assertion `btr_validate_index(index, 0, false)' failed in row_upd_sec_index_entry with virtual column and EMPTY_STRING_IS_NULL SQL mode +# +create table t1 (a int, b binary(1) generated always as (''), key(a,b)); +insert into t1 (a) values (1); +set sql_mode= default; +flush tables; +update t1 set a = 2; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` binary(1) GENERATED ALWAYS AS (NULL) VIRTUAL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 (a int, b binary(1) generated always as (''), key(a,b)); +insert into t1 (a) values (1); +set sql_mode= 'empty_string_is_null'; +flush tables; +update t1 set a = 2; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` binary(1) GENERATED ALWAYS AS ('') VIRTUAL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/main/empty_string_literal.test b/mysql-test/main/empty_string_literal.test index 71e98d872bb..9174a7714a2 100644 --- a/mysql-test/main/empty_string_literal.test +++ b/mysql-test/main/empty_string_literal.test @@ -6,3 +6,22 @@ USE test; set @mode='EMPTY_STRING_IS_NULL'; --source include/empty_string_literal.inc + +--echo # +--echo # MDEV-20763 Table corruption or Assertion `btr_validate_index(index, 0, false)' failed in row_upd_sec_index_entry with virtual column and EMPTY_STRING_IS_NULL SQL mode +--echo # +create table t1 (a int, b binary(1) generated always as (''), key(a,b)); +insert into t1 (a) values (1); +set sql_mode= default; +flush tables; +update t1 set a = 2; +show create table t1; +drop table t1; + +create table t1 (a int, b binary(1) generated always as (''), key(a,b)); +insert into t1 (a) values (1); +set sql_mode= 'empty_string_is_null'; +flush tables; +update t1 set a = 2; +show create table t1; +drop table t1; diff --git a/sql/table.cc b/sql/table.cc index 403b68551a0..22cf3357ac7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1051,7 +1051,7 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, thd->stmt_arena= table->expr_arena; thd->update_charset(&my_charset_utf8mb4_general_ci, table->s->table_charset); expr_str.append(&parse_vcol_keyword); - thd->variables.sql_mode &= ~MODE_NO_BACKSLASH_ESCAPES; + thd->variables.sql_mode &= ~(MODE_NO_BACKSLASH_ESCAPES | MODE_EMPTY_STRING_IS_NULL); while (pos < end) { From 0ee086838d4b4497599d4e0822343269b682f913 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 10 Jan 2021 21:25:17 +0100 Subject: [PATCH 09/18] MDEV-16735 mysql_upgrade failed force alter_algorithm=DEFAULT in mysql_system_tables_fix.sql, in case my.cnf sets it to something incompatible --- scripts/mysql_system_tables_fix.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 0c39e62cc9a..0a10253c5b3 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -27,6 +27,7 @@ set sql_mode=''; set storage_engine=MyISAM; set enforce_storage_engine=NULL; +set alter_algorithm=DEFAULT; ALTER TABLE user add File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; From 3ffd5f28f04a34aadabb1966b861e6bc89f7fc73 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 10 Jan 2021 21:51:36 +0100 Subject: [PATCH 10/18] MDEV-17227 Server crash in TABLE_SHARE::init_from_sql_statement_string upon table discovery with non-existent database * failed init_from_binary_frm_image can clear share->db_plugin, don't use it on the error path * cleanup the test a bit --- .../suite/federated/assisted_discovery.result | 15 +++++++++---- .../suite/federated/assisted_discovery.test | 21 +++++++++++-------- sql/table.cc | 5 ++--- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/federated/assisted_discovery.result b/mysql-test/suite/federated/assisted_discovery.result index 4818ff7bb02..e8d6663e9bc 100644 --- a/mysql-test/suite/federated/assisted_discovery.result +++ b/mysql-test/suite/federated/assisted_discovery.result @@ -13,8 +13,7 @@ CREATE TABLE t1 ( `name` varchar(32) default 'name') DEFAULT CHARSET=latin1; connection master; -CREATE TABLE t1 ENGINE=FEDERATED -CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +CREATE TABLE t1 ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -38,6 +37,9 @@ id group a\\b a\\ name 1 1 2 NULL foo 2 1 2 NULL fee DROP TABLE t1; +# +# MDEV-11311 Create federated table does not work as expected +# create table t1 ( a bigint(20) not null auto_increment, b bigint(20) not null, @@ -57,8 +59,7 @@ t1 CREATE TABLE `t1` ( KEY `b` (`b`,`c`,`d`(255)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 connection master; -create table t1 engine=federated -connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +create table t1 engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -72,6 +73,12 @@ t1 CREATE TABLE `t1` ( drop table t1; connection slave; drop table t1; +# +# MDEV-17227 Server crash in TABLE_SHARE::init_from_sql_statement_string upon table discovery with non-existent database +# +connection master; +create table t1 engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +ERROR HY000: Unable to connect to foreign data source: Table 'test.t1' doesn't exist connection master; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/assisted_discovery.test b/mysql-test/suite/federated/assisted_discovery.test index fa83a2a8e19..bd32878f811 100644 --- a/mysql-test/suite/federated/assisted_discovery.test +++ b/mysql-test/suite/federated/assisted_discovery.test @@ -13,9 +13,7 @@ CREATE TABLE t1 ( connection master; ---replace_result $SLAVE_MYPORT SLAVE_PORT -eval CREATE TABLE t1 ENGINE=FEDERATED - CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +evalp CREATE TABLE t1 ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; --replace_result $SLAVE_MYPORT SLAVE_PORT SHOW CREATE TABLE t1; @@ -30,9 +28,9 @@ connection slave; SELECT * FROM t1; DROP TABLE t1; -# -# -# +--echo # +--echo # MDEV-11311 Create federated table does not work as expected +--echo # create table t1 ( a bigint(20) not null auto_increment, b bigint(20) not null, @@ -44,9 +42,7 @@ create table t1 ( show create table t1; connection master; ---replace_result $SLAVE_MYPORT SLAVE_PORT -eval create table t1 engine=federated - connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +evalp create table t1 engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; --replace_result $SLAVE_MYPORT SLAVE_PORT show create table t1; drop table t1; @@ -54,5 +50,12 @@ drop table t1; connection slave; drop table t1; +--echo # +--echo # MDEV-17227 Server crash in TABLE_SHARE::init_from_sql_statement_string upon table discovery with non-existent database +--echo # +connection master; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +evalp create table t1 engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; + source include/federated_cleanup.inc; diff --git a/sql/table.cc b/sql/table.cc index 22cf3357ac7..254e2265633 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2869,9 +2869,8 @@ ret: if (unlikely(thd->is_error() || error)) { thd->clear_error(); - my_error(ER_SQL_DISCOVER_ERROR, MYF(0), - plugin_name(db_plugin)->str, db.str, table_name.str, - sql_copy); + my_error(ER_SQL_DISCOVER_ERROR, MYF(0), hton_name(hton)->str, + db.str, table_name.str, sql_copy); DBUG_RETURN(HA_ERR_GENERIC); } /* Treat the table as normal table from binary logging point of view */ From 59998d3480f2a472cfc79208be4ee32ff5eff1ed Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 12 Jan 2021 18:44:24 +0300 Subject: [PATCH 11/18] MDEV-23446 Missed error code fix --- sql/sql_update.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f24706fba19..3c40b003a3c 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2461,7 +2461,7 @@ error: if (has_vers_fields && table->versioned(VERS_TIMESTAMP)) { store_record(table, record[2]); - if (vers_insert_history_row(table)) + if (unlikely(error= vers_insert_history_row(table))) { restore_record(table, record[2]); goto error; From fb9a9599bc9faed7b2f4860cb5e2bc8c597aacef Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 12 Jan 2021 13:31:57 +0530 Subject: [PATCH 12/18] MDEV-24387: Wrong number of decimal digits in certain UNION/Subqery constellation Analysis: The decimals is set to NOT_FIXED_DEC for Field_str even if it is NULL. Unsigned has decimals=0. So Type_std_attributes::decimals is set to 39 (maximum between 0 and 39). This results in incorrect number of decimals when we have union of unsigned and NULL type. Fix: Check if the field is created from NULL value. If yes, set decimals to 0 otherwise set it to NOT_FIXED_DEC. --- mysql-test/main/union.result | 34 ++++++++++++++++++++++++++++++++++ mysql-test/main/union.test | 18 ++++++++++++++++++ sql/field.h | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result index ea16e621e17..a892f6c9e40 100644 --- a/mysql-test/main/union.result +++ b/mysql-test/main/union.result @@ -2601,5 +2601,39 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where `test`.`t2`.`a` < 5 except /* select#2 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where `test`.`t3`.`a` < 5 union all /* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 drop table t1,t2,t3; # +# MDEV-24387: Wrong number of decimal digits in certain UNION/Subqery +# constellation +# +SELECT CAST(1 AS UNSIGNED) UNION ALL SELECT * from (SELECT NULL) t; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def CAST(1 AS UNSIGNED) 246 2 1 Y 32896 0 63 +CAST(1 AS UNSIGNED) +1 +NULL +SELECT CAST(1 AS SIGNED) UNION ALL SELECT * from (SELECT NULL) t; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def CAST(1 AS SIGNED) 3 2 1 Y 32896 0 63 +CAST(1 AS SIGNED) +1 +NULL +SELECT CAST(1 AS SIGNED) UNION ALL SELECT * from (SELECT CAST(1 AS UNSIGNED)) t; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def CAST(1 AS SIGNED) 246 11 1 N 32897 0 63 +CAST(1 AS SIGNED) +1 +1 +SELECT CAST(1 AS UNSIGNED) UNION ALL SELECT NULL; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def CAST(1 AS UNSIGNED) 246 2 1 Y 32896 0 63 +CAST(1 AS UNSIGNED) +1 +NULL +SELECT CAST(1 AS UNSIGNED) UNION ALL SELECT CAST(1 AS SIGNED); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def CAST(1 AS UNSIGNED) 246 2 1 N 32897 0 63 +CAST(1 AS UNSIGNED) +1 +1 +# # End of 10.3 tests # diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test index 714b6abe131..ab629ce076d 100644 --- a/mysql-test/main/union.test +++ b/mysql-test/main/union.test @@ -1855,6 +1855,24 @@ select * from t1 where a > 4; drop table t1,t2,t3; +--echo # +--echo # MDEV-24387: Wrong number of decimal digits in certain UNION/Subqery +--echo # constellation +--echo # + +--disable_ps_protocol +--enable_metadata + +SELECT CAST(1 AS UNSIGNED) UNION ALL SELECT * from (SELECT NULL) t; +SELECT CAST(1 AS SIGNED) UNION ALL SELECT * from (SELECT NULL) t; +SELECT CAST(1 AS SIGNED) UNION ALL SELECT * from (SELECT CAST(1 AS UNSIGNED)) t; + +SELECT CAST(1 AS UNSIGNED) UNION ALL SELECT NULL; +SELECT CAST(1 AS UNSIGNED) UNION ALL SELECT CAST(1 AS SIGNED); + +--disable_metadata +--enable_ps_protocol + --echo # --echo # End of 10.3 tests --echo # diff --git a/sql/field.h b/sql/field.h index be3a648617b..1344774c189 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1762,7 +1762,7 @@ public: uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation); - uint decimals() const { return NOT_FIXED_DEC; } + uint decimals() const { return is_created_from_null_item ? 0 : NOT_FIXED_DEC; } int save_in_field(Field *to) { return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const { From f130adbf35b5b8ef7ed091549ed764982801480c Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Thu, 14 Jan 2021 14:31:20 +0700 Subject: [PATCH 13/18] MDEV-23666: Assertion `m_cpp_buf <= ptr && ptr <= m_cpp_buf + m_buf_length' failed in Lex_input_stream::body_utf8_append On parsing statements for which a starting backtick (`) delimiter doesn't have a corresponding ending backtick, a current pointer to a position inside a pre-processed buffer could go beyond the end of the buffer. This bug report caused by the commit d4967659032b18a5504198b41dd3d0a1813d79ef "MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds". In order to fix the issue both pointers m_ptr and m_cpp_ptr must be rolled back to previous position in raw input and pre-processed input streams correspondingly in case end of query reached during parsing. --- mysql-test/main/parser.result | 9 +++++++++ mysql-test/main/parser.test | 15 +++++++++++++++ sql/sql_lex.cc | 2 ++ 3 files changed, 26 insertions(+) diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result index 1c58c7379e4..658c26ae3e2 100644 --- a/mysql-test/main/parser.result +++ b/mysql-test/main/parser.result @@ -1784,4 +1784,13 @@ EXECUTE IMMEDIATE 'if(`systeminfo /FO LIST'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`systeminfo /FO LIST' at line 1 EXECUTE IMMEDIATE 'if(`systeminfo'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`systeminfo' at line 1 +# +# MDEV-23666 Assertion failed in Lex_input_stream::body_utf8_append +# +SET @@sql_mode='ANSI_QUOTES'; +EXECUTE IMMEDIATE 'CREATE PROCEDURE p() UPDATE t SET c=\'\'"'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '"' at line 1 +EXECUTE IMMEDIATE 'CREATE PROCEDURE p() UPDATE t SET c=\'\'"abc'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '"abc' at line 1 +SET @@sql_mode=@save_sql_mode; # End of 10.3 tests diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test index 9fb68b92b8f..738ddf5c3b1 100644 --- a/mysql-test/main/parser.test +++ b/mysql-test/main/parser.test @@ -1561,4 +1561,19 @@ EXECUTE IMMEDIATE 'if(`systeminfo /FO LIST'; --error ER_PARSE_ERROR EXECUTE IMMEDIATE 'if(`systeminfo'; +--echo # +--echo # MDEV-23666 Assertion failed in Lex_input_stream::body_utf8_append +--echo # +SET @@sql_mode='ANSI_QUOTES'; + +# Without a patch execution of the following statements results in assertion +# in Lex_input_stream::body_utf8_append on parsing the statement +--error ER_PARSE_ERROR +EXECUTE IMMEDIATE 'CREATE PROCEDURE p() UPDATE t SET c=\'\'"'; + +--error ER_PARSE_ERROR +EXECUTE IMMEDIATE 'CREATE PROCEDURE p() UPDATE t SET c=\'\'"abc'; + +SET @@sql_mode=@save_sql_mode; + --echo # End of 10.3 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6116dee6e7e..b8f6610e066 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2215,6 +2215,8 @@ int Lex_input_stream::scan_ident_delimited(THD *thd, Return the quote character, to have the parser fail on syntax error. */ m_ptr= (char *) m_tok_start + 1; + if (m_echo) + m_cpp_ptr= (char *) m_cpp_tok_start + 1; return quote_char; } int var_length= my_charlen(cs, get_ptr() - 1, get_end_of_query()); From 7d04ce6a2d42770fcc765d257c0058a859180b80 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Thu, 14 Jan 2021 18:18:06 +0200 Subject: [PATCH 14/18] MDEV-21153 Replica nodes crash due to indexed virtual columns and FK cascading delete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix for MDEV-23033 fixes a problem in replication applying of transactions, which contain cascading foreign key delete for a table, which has indexed virtual column. This fix adds slave_fk_event_map flag for table, to mark when the prelocking is needed for applying of a transaction. See commit 608b0ee52ef3e854ce14a407e64e936adbbeba23 for more details. However, this fix is targeted for async replication only, Rows_log_event::do_apply_event() has condition to rule out galera replication from the fix domain, and use cases suffering from MDEV-23033 and related MDEV-21153 will fail in galera cluster. The fix in this commit removes the condition to rule out the setting of slave_fk_event_map flag from galera replication, and makes the fix in MDEV-23033 effective for galera replication as well. Finally, a mtr test for virtual column support has been added. galera.galera_virtual_column.test has as first test a scenario from MDEV-21153 Reviewed-by: Jan Lindström --- .../galera/r/galera_virtual_column.result | 17 ++++++++ .../suite/galera/t/galera_virtual_column.test | 42 +++++++++++++++++++ sql/log_event.cc | 2 +- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/galera_virtual_column.result create mode 100644 mysql-test/suite/galera/t/galera_virtual_column.test diff --git a/mysql-test/suite/galera/r/galera_virtual_column.result b/mysql-test/suite/galera/r/galera_virtual_column.result new file mode 100644 index 00000000000..c4b425964c5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_virtual_column.result @@ -0,0 +1,17 @@ +connection node_1; +CREATE TABLE p (id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT) ENGINE = InnoDB; +CREATE TABLE c (id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, pid INT UNSIGNED, bitmap TINYINT UNSIGNED NOT NULL DEFAULT 0, bitmap5 TINYINT UNSIGNED GENERATED ALWAYS AS (bitmap&(1<<5)) VIRTUAL, FOREIGN KEY (pid) REFERENCES p (id) ON DELETE CASCADE ON UPDATE CASCADE); +CREATE INDEX bitmap5 ON c(bitmap5) USING BTREE; +INSERT INTO p VALUES(1); +INSERT INTO c(pid) VALUES(1); +connection node_2; +connection node_1; +DELETE FROM p WHERE id=1; +SELECT * FROM p; +id +SELECT * FROM c; +id pid bitmap bitmap5 +connection node_2; +connection node_1; +DROP TABLE c; +DROP TABLE p; diff --git a/mysql-test/suite/galera/t/galera_virtual_column.test b/mysql-test/suite/galera/t/galera_virtual_column.test new file mode 100644 index 00000000000..84e1da024f1 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_virtual_column.test @@ -0,0 +1,42 @@ +# +# This test is for testing virtual columnm support in galera cluster +# +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# test case for verifying that cascaded delete in a table with virtual column does not crash slave node +# + +--connection node_1 + +CREATE TABLE p (id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT) ENGINE = InnoDB; +CREATE TABLE c (id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, pid INT UNSIGNED, bitmap TINYINT UNSIGNED NOT NULL DEFAULT 0, bitmap5 TINYINT UNSIGNED GENERATED ALWAYS AS (bitmap&(1<<5)) VIRTUAL, FOREIGN KEY (pid) REFERENCES p (id) ON DELETE CASCADE ON UPDATE CASCADE); + +# not sure of this index is needed for the test +CREATE INDEX bitmap5 ON c(bitmap5) USING BTREE; + +INSERT INTO p VALUES(1); +INSERT INTO c(pid) VALUES(1); + + +--connection node_2 +# wait until both INSERTS have arrived in node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM c +--source include/wait_condition.inc + +--connection node_1 +# delete from parent table, it will cascade into child table +# node_2 might have problem in applying this cascaded delete +DELETE FROM p WHERE id=1; + +SELECT * FROM p; +SELECT * FROM c; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM c; +--source include/wait_condition.inc + +--connection node_1 +DROP TABLE c; +DROP TABLE p; diff --git a/sql/log_event.cc b/sql/log_event.cc index 48a25c8ba3d..e344fc8894f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -11357,7 +11357,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) tables->trg_event_map= new_trg_event_map; lex->query_tables_last= &tables->next_global; } - else if (!WSREP_ON) + else { tables->slave_fk_event_map= new_trg_event_map; lex->query_tables_last= &tables->next_global; From 61feb568bbbfc3ea68060bf9f59b4c3eeb999ca0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Jan 2021 15:30:19 +0100 Subject: [PATCH 15/18] remove now-unused rdiff file --- mysql-test/main/information_schema,debug.rdiff | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 mysql-test/main/information_schema,debug.rdiff diff --git a/mysql-test/main/information_schema,debug.rdiff b/mysql-test/main/information_schema,debug.rdiff deleted file mode 100644 index c4ef0a41547..00000000000 --- a/mysql-test/main/information_schema,debug.rdiff +++ /dev/null @@ -1,11 +0,0 @@ ---- mysql-test/main/information_schema.result -+++ mysql-test/main/information_schema.result -@@ -2210,7 +2210,7 @@ - SELECT * FROM INFORMATION_SCHEMA.`COLUMNS` LIMIT ROWS EXAMINED 10; - TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT IS_GENERATED GENERATION_EXPRESSION - Warnings: --Warning 1931 Query execution was interrupted. The query examined at least 671 rows, which exceeds LIMIT ROWS EXAMINED (10). The query result may be incomplete -+Warning 1931 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (10). The query result may be incomplete - # - # End of 10.2 Test - # From 4e503aec7feaeb2297035f565ca92c98d4557577 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Jan 2021 16:40:36 +0100 Subject: [PATCH 16/18] MDEV-24593 Signal 11 when group by primary key of table joined to information_schema.columns I_S tables were materialized too late, an attempt to use table statistics before the table was created caused a crash. Let's move table creation up. it only needs read_set to be calculated properly, this happens in JOIN::optimize_inner(), after semijoin transformation. Note that tables are not populated at that point, so most of the statistics would make no sense anyway. But at least field sizes will be correct. And it won't crash. --- mysql-test/main/information_schema.result | 9 ++ mysql-test/main/information_schema.test | 10 +++ sql/sql_select.cc | 6 +- sql/sql_show.cc | 102 ++++++++++++---------- sql/sql_show.h | 1 + storage/heap/ha_heap.cc | 3 - storage/maria/ha_maria.cc | 3 - 7 files changed, 79 insertions(+), 55 deletions(-) diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index 7aa7a075eb0..dc8a23bf511 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -2282,5 +2282,14 @@ create table t2 (n int); insert into t1 set n = (select table_rows from information_schema.tables where table_name='t2'); drop table t1, t2; # +# MDEV-24593 Signal 11 when group by primary key of table joined to information_schema.columns +# +create table t1 (f varchar(64) primary key); +select f from information_schema.columns i +inner join t1 on f=i.column_name +group by f; +f +drop table t1; +# # End of 10.3 tests # diff --git a/mysql-test/main/information_schema.test b/mysql-test/main/information_schema.test index 97e5fe6b0bd..018a10be255 100644 --- a/mysql-test/main/information_schema.test +++ b/mysql-test/main/information_schema.test @@ -2007,6 +2007,16 @@ create table t2 (n int); insert into t1 set n = (select table_rows from information_schema.tables where table_name='t2'); drop table t1, t2; + +--echo # +--echo # MDEV-24593 Signal 11 when group by primary key of table joined to information_schema.columns +--echo # +create table t1 (f varchar(64) primary key); +select f from information_schema.columns i +inner join t1 on f=i.column_name +group by f; +drop table t1; + --echo # --echo # End of 10.3 tests --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 203422f0b43..8baac124b71 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1556,7 +1556,7 @@ int JOIN::init_join_caches() int JOIN::optimize_inner() { - DBUG_ENTER("JOIN::optimize"); + DBUG_ENTER("JOIN::optimize_inner"); subq_exit_fl= false; do_send_rows = (unit->select_limit_cnt) ? 1 : 0; @@ -1624,6 +1624,10 @@ JOIN::optimize_inner() table_count= select_lex->leaf_tables.elements; + if (select_lex->options & OPTION_SCHEMA_TABLE && + optimize_schema_tables_memory_usage(select_lex->leaf_tables)) + DBUG_RETURN(1); + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f25a8861bc1..9a5141fa414 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8658,55 +8658,64 @@ end: } -static int optimize_schema_tables_memory_usage(TABLE_LIST *table_list) +bool optimize_schema_tables_memory_usage(List &tables) { - TABLE *table= table_list->table; - THD *thd=table->in_use; - if (!table->is_created()) + List_iterator tli(tables); + + while (TABLE_LIST *table_list= tli++) { - TMP_TABLE_PARAM *p= table_list->schema_table_param; - TMP_ENGINE_COLUMNDEF *from_recinfo, *to_recinfo; - DBUG_ASSERT(table->s->keys == 0); - DBUG_ASSERT(table->s->uniques == 0); + TABLE *table= table_list->table; + THD *thd=table->in_use; - uchar *cur= table->field[0]->ptr; - /* first recinfo could be a NULL bitmap, not an actual Field */ - from_recinfo= to_recinfo= p->start_recinfo + (cur != table->record[0]); - for (uint i=0; i < table->s->fields; i++, from_recinfo++) - { - Field *field= table->field[i]; - DBUG_ASSERT(field->vcol_info == 0); - DBUG_ASSERT(from_recinfo->length); - DBUG_ASSERT(from_recinfo->length == field->pack_length_in_rec()); - if (bitmap_is_set(table->read_set, i)) - { - field->move_field(cur); - *to_recinfo++= *from_recinfo; - cur+= from_recinfo->length; - } - else - { - field= new (thd->mem_root) Field_string(cur, 0, field->null_ptr, - field->null_bit, Field::NONE, - &field->field_name, field->dtcollation()); - field->init(table); - field->field_index= i; - DBUG_ASSERT(field->pack_length_in_rec() == 0); - table->field[i]= field; - } - } - if ((table->s->reclength= (ulong)(cur - table->record[0])) == 0) - { - /* all fields were optimized away. Force a non-0-length row */ - table->s->reclength= to_recinfo->length= 1; - to_recinfo++; - } - p->recinfo= to_recinfo; + if (!table_list->schema_table || !thd->fill_information_schema_tables()) + continue; - // TODO switch from Aria to Memory if all blobs were optimized away? - if (instantiate_tmp_table(table, p->keyinfo, p->start_recinfo, &p->recinfo, - table_list->select_lex->options | thd->variables.option_bits)) - return 1; + if (!table->is_created()) + { + TMP_TABLE_PARAM *p= table_list->schema_table_param; + TMP_ENGINE_COLUMNDEF *from_recinfo, *to_recinfo; + DBUG_ASSERT(table->s->keys == 0); + DBUG_ASSERT(table->s->uniques == 0); + + uchar *cur= table->field[0]->ptr; + /* first recinfo could be a NULL bitmap, not an actual Field */ + from_recinfo= to_recinfo= p->start_recinfo + (cur != table->record[0]); + for (uint i=0; i < table->s->fields; i++, from_recinfo++) + { + Field *field= table->field[i]; + DBUG_ASSERT(field->vcol_info == 0); + DBUG_ASSERT(from_recinfo->length); + DBUG_ASSERT(from_recinfo->length == field->pack_length_in_rec()); + if (bitmap_is_set(table->read_set, i)) + { + field->move_field(cur); + *to_recinfo++= *from_recinfo; + cur+= from_recinfo->length; + } + else + { + field= new (thd->mem_root) Field_string(cur, 0, field->null_ptr, + field->null_bit, Field::NONE, + &field->field_name, field->dtcollation()); + field->init(table); + field->field_index= i; + DBUG_ASSERT(field->pack_length_in_rec() == 0); + table->field[i]= field; + } + } + if ((table->s->reclength= (ulong)(cur - table->record[0])) == 0) + { + /* all fields were optimized away. Force a non-0-length row */ + table->s->reclength= to_recinfo->length= 1; + to_recinfo++; + } + p->recinfo= to_recinfo; + + // TODO switch from Aria to Memory if all blobs were optimized away? + if (instantiate_tmp_table(table, p->keyinfo, p->start_recinfo, &p->recinfo, + table_list->select_lex->options | thd->variables.option_bits)) + return 1; + } } return 0; } @@ -8732,9 +8741,6 @@ bool optimize_schema_tables_reads(JOIN *join) TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_information_schema_tables()) { - if (optimize_schema_tables_memory_usage(table_list)) - DBUG_RETURN(1); - /* A value of 0 indicates a dummy implementation */ if (table_list->schema_table->fill_table == 0) continue; diff --git a/sql/sql_show.h b/sql/sql_show.h index 39cbc35230a..c1845d8c1b3 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -238,6 +238,7 @@ public: }; bool optimize_schema_tables_reads(JOIN *join); +bool optimize_schema_tables_memory_usage(List &tables); /* Handle the ignored database directories list for SHOW/I_S. */ bool ignore_db_dirs_init(); diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index a40f4b8a464..5af68f098a4 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -363,9 +363,6 @@ int ha_heap::info(uint flag) { HEAPINFO hp_info; - if (!table) - return 0; - (void) heap_info(file,&hp_info,flag); errkey= hp_info.errkey; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 23d2becbb04..c0163473f3a 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2440,9 +2440,6 @@ int ha_maria::info(uint flag) MARIA_INFO maria_info; char name_buff[FN_REFLEN]; - if (!table) - return 0; - (void) maria_status(file, &maria_info, flag); if (flag & HA_STATUS_VARIABLE) { From 0e10d7ea14cf795ada8aee7fe1afc590ef6de32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 22 Jan 2021 16:44:17 +0200 Subject: [PATCH 17/18] MDEV-22351 InnoDB may recover wrong information after RESET MASTER Ever since commit 947efe17ed8188ca4feef6deb0c2831a246b5c8f InnoDB no longer writes binlog position in one place. It will not at all be written to the TRX_SYS page, and instead it will be written to the undo log header page that changes the transaction state. trx_rseg_mem_restore(): Recover the information from the latest written page. --- storage/innobase/include/trx0sys.h | 6 ++-- storage/innobase/trx/trx0rseg.cc | 48 +++++++++++++----------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index b8ccb2726b2..30ee5f5833d 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 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 @@ -857,8 +857,10 @@ public: #endif /** Latest recovered binlog offset */ uint64_t recovered_binlog_offset; - /** Latest recovred binlog file name */ + /** Latest recovered binlog file name */ char recovered_binlog_filename[TRX_SYS_MYSQL_LOG_NAME_LEN]; + /** FIL_PAGE_LSN of the page with the latest recovered binlog metadata */ + lsn_t recovered_binlog_lsn; /** diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index dfc8e5cbcca..d6720979716 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 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 @@ -439,8 +439,14 @@ static void trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr) { - trx_rsegf_t* rseg_header = trx_rsegf_get_new( - rseg->space->id, rseg->page_no, mtr); + /* This is based on trx_rsegf_get_new(). + We need to access buf_block_t. */ + buf_block_t *block = buf_page_get( + page_id_t(rseg->space->id, rseg->page_no), + univ_page_size, RW_S_LATCH, mtr); + buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); + + const trx_rsegf_t* rseg_header = TRX_RSEG + block->frame; if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT) == 0) { trx_id_t id = mach_read_from_8(rseg_header @@ -451,32 +457,20 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr) } if (rseg_header[TRX_RSEG_BINLOG_NAME]) { - const char* binlog_name = reinterpret_cast - (rseg_header) + TRX_RSEG_BINLOG_NAME; + lsn_t lsn = std::max(block->page.newest_modification, + mach_read_from_8(FIL_PAGE_LSN + + block->frame)); compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof trx_sys.recovered_binlog_filename); - - int cmp = *trx_sys.recovered_binlog_filename - ? strncmp(binlog_name, - trx_sys.recovered_binlog_filename, - TRX_RSEG_BINLOG_NAME_LEN) - : 1; - - if (cmp >= 0) { - uint64_t binlog_offset = mach_read_from_8( - rseg_header + TRX_RSEG_BINLOG_OFFSET); - if (cmp) { - memcpy(trx_sys. - recovered_binlog_filename, - binlog_name, - TRX_RSEG_BINLOG_NAME_LEN); - trx_sys.recovered_binlog_offset - = binlog_offset; - } else if (binlog_offset > - trx_sys.recovered_binlog_offset) { - trx_sys.recovered_binlog_offset - = binlog_offset; - } + if (lsn > trx_sys.recovered_binlog_lsn) { + trx_sys.recovered_binlog_lsn = lsn; + trx_sys.recovered_binlog_offset + = mach_read_from_8( + rseg_header + + TRX_RSEG_BINLOG_OFFSET); + memcpy(trx_sys.recovered_binlog_filename, + rseg_header + TRX_RSEG_BINLOG_NAME, + TRX_RSEG_BINLOG_NAME_LEN); } #ifdef WITH_WSREP From eaeb8ec4b87882711ecb8e1c7476a6e410d5d2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 25 Jan 2021 10:24:35 +0200 Subject: [PATCH 18/18] MDEV-24653 Assertion block->page.id.page_no() == index->page failed in innobase_add_instant_try() We may end up with an empty leaf page (containing only an ADD COLUMN metadata record) that is not the root page. innobase_add_instant_try(): Disable an optimization for a non-canonical empty table that contains a metadata record somewhere else than in the root page. btr_pcur_store_position(): Tolerate a non-canonical empty table. --- .../suite/innodb/r/instant_alter_debug.result | 19 +++++++++++++- .../suite/innodb/t/instant_alter_debug.test | 25 +++++++++++++++++-- storage/innobase/btr/btr0pcur.cc | 19 +++++++++++--- storage/innobase/handler/handler0alter.cc | 8 +++--- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 49365b6e9be..230097f47c7 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -263,7 +263,6 @@ a b vb 4 NULL NULL 5 NULL NULL DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; # # MDEV-21045 AddressSanitizer: use-after-poison in mem_heap_dup / row_log_table_get_pk_col # @@ -282,3 +281,21 @@ connection default; SET DEBUG_SYNC='RESET'; disconnect con2; DROP TABLE t1; +# +# MDEV-24653 Assertion block->page.id.page_no() == index->page failed +# in innobase_add_instant_try() +# +SET @saved_limit = @@GLOBAL.innodb_limit_optimistic_insert_debug; +SET GLOBAL innodb_limit_optimistic_insert_debug = 2; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4); +ALTER TABLE t1 ADD COLUMN b INT; +DELETE FROM t1; +InnoDB 0 transactions not purged +ALTER TABLE t1 ADD COLUMN c INT; +SELECT * FROM t1; +a b c +DROP TABLE t1; +SET GLOBAL innodb_limit_optimistic_insert_debug = @saved_limit; +# End of 10.3 tests +SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index cec7a05725b..d3aea85b243 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -292,8 +292,6 @@ CHECK TABLE t1; SELECT * FROM t1; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; - --echo # --echo # MDEV-21045 AddressSanitizer: use-after-poison in mem_heap_dup / row_log_table_get_pk_col --echo # @@ -319,3 +317,26 @@ SET DEBUG_SYNC='now SIGNAL update'; SET DEBUG_SYNC='RESET'; --disconnect con2 DROP TABLE t1; + +--echo # +--echo # MDEV-24653 Assertion block->page.id.page_no() == index->page failed +--echo # in innobase_add_instant_try() +--echo # + +SET @saved_limit = @@GLOBAL.innodb_limit_optimistic_insert_debug; +SET GLOBAL innodb_limit_optimistic_insert_debug = 2; + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4); +ALTER TABLE t1 ADD COLUMN b INT; +DELETE FROM t1; +--source include/wait_all_purged.inc +ALTER TABLE t1 ADD COLUMN c INT; + +SELECT * FROM t1; +DROP TABLE t1; +SET GLOBAL innodb_limit_optimistic_insert_debug = @saved_limit; + +--echo # End of 10.3 tests + +SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 019369d997d..8faa6c626ff 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2020, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -128,13 +128,14 @@ btr_pcur_store_position( cursor->old_stored = true; if (page_is_empty(block->frame)) { + ut_ad(block->page.id.page_no() == index->page); +empty_table: /* It must be an empty index tree; NOTE that in this case we do not store the modify_clock, but always do a search if we restore the cursor position */ ut_a(!page_has_siblings(block->frame)); ut_ad(page_is_leaf(block->frame)); - ut_ad(block->page.id.page_no() == index->page); if (page_rec_is_supremum_low(offs)) { cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; @@ -150,7 +151,15 @@ before_first: rec = page_rec_get_prev(rec); ut_ad(!page_rec_is_infimum(rec)); - ut_ad(!rec_is_metadata(rec, index)); + + if (UNIV_UNLIKELY(rec_is_metadata(rec, index))) { + /* The table may be empty such that it only + contains a metadata record, in a leaf page + that is not the root page. */ + ut_ad(index->is_primary()); + ut_ad(block->page.id.page_no() != index->page); + goto empty_table; + } cursor->rel_pos = BTR_PCUR_AFTER; } else if (page_rec_is_infimum_low(offs)) { @@ -160,7 +169,9 @@ before_first: ut_ad(!page_has_prev(block->frame)); rec = page_rec_get_next(rec); if (page_rec_is_supremum(rec)) { - ut_ad(page_has_next(block->frame)); + ut_ad(page_has_next(block->frame) + || block->page.id.page_no() + != index->page); goto before_first; } } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 574b29a261e..6d4e545248a 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 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 @@ -4482,11 +4482,13 @@ innobase_add_instant_try( const rec_t* rec = btr_pcur_get_rec(&pcur); que_thr_t* thr = pars_complete_graph_for_exec( NULL, trx, ctx->heap, NULL); + const bool is_root = block->page.id.page_no() == index->page; dberr_t err; if (rec_is_metadata(rec, index)) { ut_ad(page_rec_is_user_rec(rec)); - if (!page_has_next(block->frame) + if (is_root + && !page_has_next(block->frame) && page_rec_is_last(rec, block->frame)) { goto empty_table; } @@ -4528,7 +4530,7 @@ innobase_add_instant_try( } btr_pcur_close(&pcur); goto func_exit; - } else if (page_rec_is_supremum(rec)) { + } else if (is_root && page_rec_is_supremum(rec)) { empty_table: /* The table is empty. */ ut_ad(fil_page_index_page_check(block->frame));