From 35ee4aa4e3bf391b7de78b3e95f3e484394fd1ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 31 Mar 2021 09:06:44 +0300 Subject: [PATCH 01/35] MDEV-13103 fixup: Actually fix a crash during IMPORT TABLESPACE --- storage/innobase/ibuf/ibuf0ibuf.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index ee6fd235d5e..46649187ca0 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 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 @@ -4922,6 +4922,13 @@ ibuf_check_bitmap_on_import( bitmap_page = ibuf_bitmap_get_map_page( page_id_t(space_id, page_no), page_size, &mtr); + if (!bitmap_page) { + mutex_exit(&ibuf_mutex); + ibuf_exit(&mtr); + mtr_commit(&mtr); + return DB_CORRUPTION; + } + if (buf_is_zeroes(span(bitmap_page, page_size.physical()))) { /* This means we got all-zero page instead of @@ -4945,11 +4952,6 @@ ibuf_check_bitmap_on_import( continue; } - if (!bitmap_page) { - mutex_exit(&ibuf_mutex); - return DB_CORRUPTION; - } - for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < page_size.physical(); i++) { From 08cb5d848314006111b0c379db6a1fce220579aa Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 31 Mar 2021 14:23:56 +0200 Subject: [PATCH 02/35] MDEV-25221 Do not remove source file, if copy_file() fails in mariabackup --move-back Remove an incompletely copied destination file. --- extra/mariabackup/backup_copy.cc | 14 +++++++---- extra/mariabackup/datasink.h | 6 +++++ extra/mariabackup/ds_archive.cc | 1 + extra/mariabackup/ds_buffer.cc | 1 + extra/mariabackup/ds_compress.cc | 1 + extra/mariabackup/ds_local.cc | 6 +++++ extra/mariabackup/ds_stdout.cc | 1 + extra/mariabackup/ds_tmpfile.cc | 1 + extra/mariabackup/ds_xbstream.cc | 1 + .../mariabackup/error_during_copyback.result | 9 +++++++ .../mariabackup/error_during_copyback.test | 25 +++++++++++++++++++ 11 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/mariabackup/error_during_copyback.result create mode 100644 mysql-test/suite/mariabackup/error_during_copyback.test diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index d3fa3605c21..5637ec3d4d7 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1066,6 +1066,7 @@ copy_file(ds_ctxt_t *datasink, ds_file_t *dstfile = NULL; datafile_cur_t cursor; xb_fil_cur_result_t res; + DBUG_ASSERT(datasink->datasink->remove); const char *dst_path = (xtrabackup_copy_back || xtrabackup_move_back)? dst_file_path : trim_dotslash(dst_file_path); @@ -1091,6 +1092,7 @@ copy_file(ds_ctxt_t *datasink, if (ds_write(dstfile, cursor.buf, cursor.buf_read)) { goto error; } + DBUG_EXECUTE_IF("copy_file_error", errno=ENOSPC;goto error;); } if (res == XB_FIL_CUR_ERROR) { @@ -1112,6 +1114,7 @@ copy_file(ds_ctxt_t *datasink, error: datafile_close(&cursor); if (dstfile != NULL) { + datasink->datasink->remove(dstfile->path); ds_close(dstfile); } @@ -1156,17 +1159,18 @@ move_file(ds_ctxt_t *datasink, if (my_rename(src_file_path, dst_file_path_abs, MYF(0)) != 0) { if (my_errno == EXDEV) { - bool ret; - ret = copy_file(datasink, src_file_path, - dst_file_path, thread_n); + /* Fallback to copy/unlink */ + if(!copy_file(datasink, src_file_path, + dst_file_path, thread_n)) + return false; msg(thread_n,"Removing %s", src_file_path); if (unlink(src_file_path) != 0) { my_strerror(errbuf, sizeof(errbuf), errno); - msg("Error: unlink %s failed: %s", + msg("Warning: unlink %s failed: %s", src_file_path, errbuf); } - return(ret); + return true; } my_strerror(errbuf, sizeof(errbuf), my_errno); msg("Can not move file %s to %s: %s", diff --git a/extra/mariabackup/datasink.h b/extra/mariabackup/datasink.h index 201bbfd3267..5c82556b9ba 100644 --- a/extra/mariabackup/datasink.h +++ b/extra/mariabackup/datasink.h @@ -50,9 +50,15 @@ struct datasink_struct { ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat); int (*write)(ds_file_t *file, const unsigned char *buf, size_t len); int (*close)(ds_file_t *file); + int (*remove)(const char *path); void (*deinit)(ds_ctxt_t *ctxt); }; + +static inline int dummy_remove(const char *) { + return 0; +} + /* Supported datasink types */ typedef enum { DS_TYPE_STDOUT, diff --git a/extra/mariabackup/ds_archive.cc b/extra/mariabackup/ds_archive.cc index 3826029e120..18f13fbcf3a 100644 --- a/extra/mariabackup/ds_archive.cc +++ b/extra/mariabackup/ds_archive.cc @@ -56,6 +56,7 @@ datasink_t datasink_archive = { &archive_open, &archive_write, &archive_close, + &dummy_remove, &archive_deinit }; diff --git a/extra/mariabackup/ds_buffer.cc b/extra/mariabackup/ds_buffer.cc index e906edc9e84..9dc040d533b 100644 --- a/extra/mariabackup/ds_buffer.cc +++ b/extra/mariabackup/ds_buffer.cc @@ -54,6 +54,7 @@ datasink_t datasink_buffer = { &buffer_open, &buffer_write, &buffer_close, + &dummy_remove, &buffer_deinit }; diff --git a/extra/mariabackup/ds_compress.cc b/extra/mariabackup/ds_compress.cc index fb4f3a75bb6..23de4d85116 100644 --- a/extra/mariabackup/ds_compress.cc +++ b/extra/mariabackup/ds_compress.cc @@ -74,6 +74,7 @@ datasink_t datasink_compress = { &compress_open, &compress_write, &compress_close, + &dummy_remove, &compress_deinit }; diff --git a/extra/mariabackup/ds_local.cc b/extra/mariabackup/ds_local.cc index 0f13ddfe9a9..2f0ad2d8705 100644 --- a/extra/mariabackup/ds_local.cc +++ b/extra/mariabackup/ds_local.cc @@ -44,12 +44,18 @@ static int local_write(ds_file_t *file, const uchar *buf, size_t len); static int local_close(ds_file_t *file); static void local_deinit(ds_ctxt_t *ctxt); +static int local_remove(const char *path) +{ + return unlink(path); +} + extern "C" { datasink_t datasink_local = { &local_init, &local_open, &local_write, &local_close, + &local_remove, &local_deinit }; } diff --git a/extra/mariabackup/ds_stdout.cc b/extra/mariabackup/ds_stdout.cc index 9398482feb9..a4abbe426b6 100644 --- a/extra/mariabackup/ds_stdout.cc +++ b/extra/mariabackup/ds_stdout.cc @@ -39,6 +39,7 @@ datasink_t datasink_stdout = { &stdout_open, &stdout_write, &stdout_close, + &dummy_remove, &stdout_deinit }; diff --git a/extra/mariabackup/ds_tmpfile.cc b/extra/mariabackup/ds_tmpfile.cc index ddb23bf469d..9eadd36bec0 100644 --- a/extra/mariabackup/ds_tmpfile.cc +++ b/extra/mariabackup/ds_tmpfile.cc @@ -50,6 +50,7 @@ datasink_t datasink_tmpfile = { &tmpfile_open, &tmpfile_write, &tmpfile_close, + &dummy_remove, &tmpfile_deinit }; diff --git a/extra/mariabackup/ds_xbstream.cc b/extra/mariabackup/ds_xbstream.cc index 105c89d05f7..3b60456f8ed 100644 --- a/extra/mariabackup/ds_xbstream.cc +++ b/extra/mariabackup/ds_xbstream.cc @@ -50,6 +50,7 @@ datasink_t datasink_xbstream = { &xbstream_open, &xbstream_write, &xbstream_close, + &dummy_remove, &xbstream_deinit }; diff --git a/mysql-test/suite/mariabackup/error_during_copyback.result b/mysql-test/suite/mariabackup/error_during_copyback.result new file mode 100644 index 00000000000..9b12c1135d2 --- /dev/null +++ b/mysql-test/suite/mariabackup/error_during_copyback.result @@ -0,0 +1,9 @@ +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); +# xtrabackup backup +# xtrabackup prepare +# restart server +SELECT * FROM t; +i +1 +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/error_during_copyback.test b/mysql-test/suite/mariabackup/error_during_copyback.test new file mode 100644 index 00000000000..3ec9fbfc3c3 --- /dev/null +++ b/mysql-test/suite/mariabackup/error_during_copyback.test @@ -0,0 +1,25 @@ +--source include/have_debug.inc +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); +echo # xtrabackup backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +let $_datadir= `SELECT @@datadir`; +--source include/shutdown_mysqld.inc +rmdir $_datadir; +error 1; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir --dbug=+d,copy_file_error; +list_files $_datadir; +rmdir $_datadir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir; +echo # restart server; +--source include/start_mysqld.inc +SELECT * FROM t; +DROP TABLE t; +rmdir $targetdir; + From 453bac08c265046f2aba4589c5a7f2f8287cb352 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 31 Mar 2021 14:26:10 +0200 Subject: [PATCH 03/35] CMake - when searching bison, look also for win_bison win_bison belongs winflexbison project, which is Windows most up-to-date bison distro. --- cmake/bison.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/bison.cmake b/cmake/bison.cmake index 717cd50dedd..1b2d1c38bae 100644 --- a/cmake/bison.cmake +++ b/cmake/bison.cmake @@ -27,7 +27,7 @@ IF(WIN32) C:/cygwin64/bin C:/cygwin/bin) ENDIF() -FIND_PROGRAM(BISON_EXECUTABLE bison +FIND_PROGRAM(BISON_EXECUTABLE NAMES bison win_bison ${BISON_PATH_HINTS} DOC "path to the bison executable") MARK_AS_ADVANCED(BISON_EXECUTABLE "") From b9d1c6574b845ddf843dd5a8e506593e74352c69 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 25 Jan 2021 13:02:28 +0300 Subject: [PATCH 04/35] MDEV-23446 goto error cleanup --- sql/sql_update.cc | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ff301267484..c66a474c18b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2350,10 +2350,10 @@ int multi_update::send_data(List ¬_used_values) { TABLE_LIST *cur_table; DBUG_ENTER("multi_update::send_data"); - int error= 0; for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) { + int error= 0; TABLE *table= cur_table->table; uint offset= cur_table->shared; /* @@ -2423,21 +2423,7 @@ int multi_update::send_data(List ¬_used_values) updated--; if (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL)) - { -error: - /* - If (ignore && error == is ignorable) we don't have to - do anything; otherwise... - */ - myf flags= 0; - - if (table->file->is_fatal_error(error, HA_CHECK_ALL)) - flags|= ME_FATALERROR; /* Other handler errors are fatal */ - - prepare_record_for_error_message(error, table); - table->file->print_error(error,MYF(flags)); - DBUG_RETURN(1); - } + goto error; } else { @@ -2513,7 +2499,22 @@ error: } } } - } + continue; +error: + DBUG_ASSERT(error > 0); + /* + If (ignore && error == is ignorable) we don't have to + do anything; otherwise... + */ + myf flags= 0; + + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) + flags|= ME_FATALERROR; /* Other handler errors are fatal */ + + prepare_record_for_error_message(error, table); + table->file->print_error(error,MYF(flags)); + DBUG_RETURN(1); + } // for (cur_table) DBUG_RETURN(0); } From af52a0e516aa044b7fcdf91b3d2a7036c6c7ae9f Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Fri, 5 Feb 2021 01:52:21 +0300 Subject: [PATCH 05/35] MDEV-24690 Dropping primary key column from versioned table always fails with 1072 Exclude system-invisible key-parts from MDEV-11114 (04b288ae) restriction. --- mysql-test/suite/versioning/r/alter.result | 42 ++++++++++++++++++++++ mysql-test/suite/versioning/t/alter.test | 29 +++++++++++++++ sql/sql_table.cc | 5 ++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result index 2ecd5152a45..9d79b6e73c5 100644 --- a/mysql-test/suite/versioning/r/alter.result +++ b/mysql-test/suite/versioning/r/alter.result @@ -693,3 +693,45 @@ delete from t1; set statement system_versioning_alter_history=keep for alter table t1 drop system versioning, modify column a tinyint; drop table t1; +# +# MDEV-24690 Dropping primary key column from versioned table always fails with 1072 +# +create table t1 (a int, b int primary key) with system versioning; +alter table t1 drop column b; +create or replace table t1 ( +a int, b int primary key, +row_start timestamp(6) as row start, +row_end timestamp(6) as row end, +period for system_time(row_start, row_end) +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) NOT NULL, + `row_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `row_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PRIMARY KEY (`b`,`row_end`), + PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t1 drop column b; +ERROR 42000: Key column 'b' doesn't exist in table +create or replace table t1 ( +a int, b int primary key, +row_start timestamp(6) as row start invisible, +row_end timestamp(6) as row end invisible, +period for system_time(row_start, row_end) +) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) NOT NULL, + `row_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE, + `row_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE, + PRIMARY KEY (`b`,`row_end`), + PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t1 drop column b; +ERROR 42000: Key column 'b' doesn't exist in table +drop table t1; diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test index 9d8f0a1bb7b..90ecbfd9f79 100644 --- a/mysql-test/suite/versioning/t/alter.test +++ b/mysql-test/suite/versioning/t/alter.test @@ -592,3 +592,32 @@ alter table t1 drop system versioning, modify column a tinyint; # cleanup drop table t1; + +--echo # +--echo # MDEV-24690 Dropping primary key column from versioned table always fails with 1072 +--echo # +create table t1 (a int, b int primary key) with system versioning; +alter table t1 drop column b; + +create or replace table t1 ( + a int, b int primary key, + row_start timestamp(6) as row start, + row_end timestamp(6) as row end, + period for system_time(row_start, row_end) +) with system versioning; +show create table t1; +--error ER_KEY_COLUMN_DOES_NOT_EXITS +alter table t1 drop column b; + +create or replace table t1 ( +a int, b int primary key, + row_start timestamp(6) as row start invisible, + row_end timestamp(6) as row end invisible, + period for system_time(row_start, row_end) +) with system versioning; +show create table t1; +--error ER_KEY_COLUMN_DOES_NOT_EXITS +alter table t1 drop column b; + +# cleanup +drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 61b6023c6a1..01812e039be 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8375,6 +8375,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, } const char *dropped_key_part= NULL; + bool user_keyparts= false; // some user-defined keyparts left KEY_PART_INFO *key_part= key_info->key_part; key_parts.empty(); bool delete_index_stat= FALSE; @@ -8450,6 +8451,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, key_parts.push_back(new (thd->mem_root) Key_part_spec(&cfield->field_name, key_part_length, true), thd->mem_root); + if (cfield->invisible < INVISIBLE_SYSTEM) + user_keyparts= true; } if (table->s->tmp_table == NO_TMP_TABLE) { @@ -8493,7 +8496,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, key_type= Key::PRIMARY; else key_type= Key::UNIQUE; - if (dropped_key_part) + if (dropped_key_part && user_keyparts) { my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), dropped_key_part); goto err; From 0c99e6e9a6a5a64b0d757d796ab53d361e7fb001 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sun, 14 Feb 2021 23:26:12 +0300 Subject: [PATCH 06/35] MDEV-22562 Assertion `next_insert_id == 0' upon UPDATE on system-versioned table Don't update autoinc counter on history row insert. Uniqueness is kept due to merge with row_end. --- .../{auto_increment.result => autoinc.result} | 10 ++++++++++ .../t/{auto_increment.test => autoinc.test} | 13 ++++++++++++ sql/handler.cc | 20 ++++++++++--------- 3 files changed, 34 insertions(+), 9 deletions(-) rename mysql-test/suite/versioning/r/{auto_increment.result => autoinc.result} (84%) rename mysql-test/suite/versioning/t/{auto_increment.test => autoinc.test} (82%) diff --git a/mysql-test/suite/versioning/r/auto_increment.result b/mysql-test/suite/versioning/r/autoinc.result similarity index 84% rename from mysql-test/suite/versioning/r/auto_increment.result rename to mysql-test/suite/versioning/r/autoinc.result index 8ff1bed8fe3..e785c5d300e 100644 --- a/mysql-test/suite/versioning/r/auto_increment.result +++ b/mysql-test/suite/versioning/r/autoinc.result @@ -63,3 +63,13 @@ A x y x y 1 7 17 7 17 drop table t1; drop table t2; +# +# MDEV-22562 Assertion `next_insert_id == 0' upon UPDATE on system-versioned table +# +create table t1 (pk integer auto_increment primary key) engine=myisam with system versioning; +insert delayed into t1 (pk) values (1); +lock tables t1 write; +update t1 set pk= 0; +update t1 set pk= 0; +unlock tables; +drop table t1; diff --git a/mysql-test/suite/versioning/t/auto_increment.test b/mysql-test/suite/versioning/t/autoinc.test similarity index 82% rename from mysql-test/suite/versioning/t/auto_increment.test rename to mysql-test/suite/versioning/t/autoinc.test index 804c0424179..7c87c17301a 100644 --- a/mysql-test/suite/versioning/t/auto_increment.test +++ b/mysql-test/suite/versioning/t/autoinc.test @@ -47,4 +47,17 @@ select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner jo drop table t1; drop table t2; +--echo # +--echo # MDEV-22562 Assertion `next_insert_id == 0' upon UPDATE on system-versioned table +--echo # +create table t1 (pk integer auto_increment primary key) engine=myisam with system versioning; +insert delayed into t1 (pk) values (1); +lock tables t1 write; +update t1 set pk= 0; +update t1 set pk= 0; +unlock tables; + +# cleanup +drop table t1; + -- source suite/versioning/common_finish.inc diff --git a/sql/handler.cc b/sql/handler.cc index 79dcee037a5..334ed2d8be2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3326,25 +3326,27 @@ int handler::update_auto_increment() DBUG_RETURN(0); } - // ALTER TABLE ... ADD COLUMN ... AUTO_INCREMENT - if (thd->lex->sql_command == SQLCOM_ALTER_TABLE) + if (table->versioned()) { - if (table->versioned()) + Field *end= table->vers_end_field(); + DBUG_ASSERT(end); + bitmap_set_bit(table->read_set, end->field_index); + if (!end->is_max()) { - Field *end= table->vers_end_field(); - DBUG_ASSERT(end); - bitmap_set_bit(table->read_set, end->field_index); - if (!end->is_max()) + if (thd->lex->sql_command == SQLCOM_ALTER_TABLE) { if (!table->next_number_field->real_maybe_null()) DBUG_RETURN(HA_ERR_UNSUPPORTED); table->next_number_field->set_null(); - DBUG_RETURN(0); } + DBUG_RETURN(0); } - table->next_number_field->set_notnull(); } + // ALTER TABLE ... ADD COLUMN ... AUTO_INCREMENT + if (thd->lex->sql_command == SQLCOM_ALTER_TABLE) + table->next_number_field->set_notnull(); + if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum()) { /* next_insert_id is beyond what is reserved, so we reserve more. */ From 77ffbbca49064291817430cd29afc160dfe4a706 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 24 Mar 2021 20:34:16 +0300 Subject: [PATCH 07/35] MDEV-25172 Wrong error message for ADD COLUMN .. AS ROW START Handle one more condition in fix_alter_info() for non-versioned table and produce ER_VERS_NOT_VERSIONED error. --- mysql-test/suite/versioning/r/alter.result | 9 ++++++++- mysql-test/suite/versioning/t/alter.test | 11 ++++++++++- sql/handler.cc | 5 +++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result index 9d79b6e73c5..3666a5ddcb1 100644 --- a/mysql-test/suite/versioning/r/alter.result +++ b/mysql-test/suite/versioning/r/alter.result @@ -80,7 +80,7 @@ t CREATE TABLE `t` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 alter table t add column trx_start timestamp(6) as row start; -ERROR HY000: Duplicate ROW START column `trx_start` +ERROR HY000: Table `t` is not system-versioned alter table t add system versioning; show create table t; Table Create Table @@ -735,3 +735,10 @@ t1 CREATE TABLE `t1` ( alter table t1 drop column b; ERROR 42000: Key column 'b' doesn't exist in table drop table t1; +# +# MDEV-25172 Wrong error message for ADD COLUMN .. AS ROW START +# +create or replace table t1 (x int); +alter table t1 add column y timestamp(6) as row start; +ERROR HY000: Table `t1` is not system-versioned +drop table t1; diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test index 90ecbfd9f79..91bddb5aaeb 100644 --- a/mysql-test/suite/versioning/t/alter.test +++ b/mysql-test/suite/versioning/t/alter.test @@ -68,7 +68,7 @@ select row_start from t; alter table t drop system versioning; show create table t; ---error ER_VERS_DUPLICATE_ROW_START_END +--error ER_VERS_NOT_VERSIONED alter table t add column trx_start timestamp(6) as row start; alter table t add system versioning; @@ -621,3 +621,12 @@ alter table t1 drop column b; # cleanup drop table t1; + +--echo # +--echo # MDEV-25172 Wrong error message for ADD COLUMN .. AS ROW START +--echo # +create or replace table t1 (x int); +--error ER_VERS_NOT_VERSIONED +alter table t1 add column y timestamp(6) as row start; +# cleanup +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index 334ed2d8be2..c0a810a72bc 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7340,6 +7340,11 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info, { if (f->flags & VERS_SYSTEM_FIELD) { + if (!table->versioned()) + { + my_error(ER_VERS_NOT_VERSIONED, MYF(0), table->s->table_name.str); + return true; + } my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0), f->flags & VERS_SYS_START_FLAG ? "START" : "END", f->field_name.str); return true; From f93e087d745a0c24e30aa144c0f9d34fa042e21b Mon Sep 17 00:00:00 2001 From: mkaruza Date: Wed, 31 Mar 2021 11:29:51 +0200 Subject: [PATCH 08/35] MDEV-25047: SIGSEGV in mach_read_from_n_little_endian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Virtual column fields are not found in prebuilt data type, so we should match InnoDB fields with `get_innobase_type_from_mysql_type` method. Reviewed-by: Jan Lindström --- .../suite/galera/r/galera_virtual_blob.result | 19 +++++++++++++++++++ .../suite/galera/t/galera_virtual_blob.test | 10 ++++++++++ storage/innobase/handler/ha_innodb.cc | 5 ++++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/galera_virtual_blob.result create mode 100644 mysql-test/suite/galera/t/galera_virtual_blob.test diff --git a/mysql-test/suite/galera/r/galera_virtual_blob.result b/mysql-test/suite/galera/r/galera_virtual_blob.result new file mode 100644 index 00000000000..91952b1d52d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_virtual_blob.result @@ -0,0 +1,19 @@ +CREATE TABLE t (f INT GENERATED ALWAYS AS (a+b)VIRTUAL,a INT,b INT,h BLOB); +INSERT INTO t (a,b)VALUES(0,0), (0,0), (0,0), (0,0), (0,0); +SELECT * from t; +f a b h +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +connection node_2; +SELECT * from t; +f a b h +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +connection node_1; +DROP TABLE t; diff --git a/mysql-test/suite/galera/t/galera_virtual_blob.test b/mysql-test/suite/galera/t/galera_virtual_blob.test new file mode 100644 index 00000000000..a10e3025668 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_virtual_blob.test @@ -0,0 +1,10 @@ +--source include/galera_cluster.inc + +CREATE TABLE t (f INT GENERATED ALWAYS AS (a+b)VIRTUAL,a INT,b INT,h BLOB); +INSERT INTO t (a,b)VALUES(0,0), (0,0), (0,0), (0,0), (0,0); +SELECT * from t; + +--connection node_2 +SELECT * from t; +--connection node_1 +DROP TABLE t; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 445103e0550..fc876e6f753 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8874,6 +8874,8 @@ wsrep_calc_row_hash( for (uint i = 0; i < table->s->fields; i++) { byte null_byte=0; byte true_byte=1; + ulint col_type; + ulint is_unsigned; const Field* field = table->field[i]; if (!field->stored_in_db()) { @@ -8882,8 +8884,9 @@ wsrep_calc_row_hash( ptr = (const byte*) row + get_field_offset(table, field); len = field->pack_length(); + col_type = get_innobase_type_from_mysql_type(&is_unsigned, field); - switch (prebuilt->table->cols[i].mtype) { + switch (col_type) { case DATA_BLOB: ptr = row_mysql_read_blob_ref(&len, ptr, len); From 5bc5ecce081d235ac6faed0e22885b3a22e6edee Mon Sep 17 00:00:00 2001 From: Srinidhi Kaushik Date: Thu, 1 Apr 2021 15:03:59 +0530 Subject: [PATCH 09/35] MDEV-24197: Add "innodb_force_recovery" for "mariabackup --prepare" During the prepare phase of restoring backups, "mariabackup" does not seem to allow (or recognize) the option "innodb_force_recovery" for the embedded InnoDB server instance that it starts. If page corruption observed during page recovery, the prepare step fails. While this is indeed the correct behavior ideally, allowing this option to be set in case of emergencies might be useful when the current backup is the only copy available. Some error messages during "--prepare" suggest to set "innodb_force_recovery" to 1: [ERROR] InnoDB: Set innodb_force_recovery=1 to ignore corruption. For backwards compatibility, "mariabackup --innobackupex --apply-log" should also have this option. Signed-off-by: Srinidhi Kaushik --- extra/mariabackup/innobackupex.cc | 14 +- extra/mariabackup/xtrabackup.cc | 60 +++++++- extra/mariabackup/xtrabackup.h | 2 + .../mariabackup/innodb_force_recovery.result | 26 ++++ .../mariabackup/innodb_force_recovery.test | 138 ++++++++++++++++++ storage/innobase/srv/srv0start.cc | 2 +- 6 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 mysql-test/suite/mariabackup/innodb_force_recovery.result create mode 100644 mysql-test/suite/mariabackup/innodb_force_recovery.test diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index f1627dd1bc5..fefd81dc1be 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -206,7 +206,8 @@ enum innobackupex_options OPT_STREAM, OPT_TABLES_FILE, OPT_THROTTLE, - OPT_USE_MEMORY + OPT_USE_MEMORY, + OPT_INNODB_FORCE_RECOVERY, }; ibx_mode_t ibx_mode = IBX_MODE_BACKUP; @@ -624,6 +625,16 @@ static struct my_option ibx_long_options[] = 0, GET_LL, REQUIRED_ARG, 100*1024*1024L, 1024*1024L, LONGLONG_MAX, 0, 1024*1024L, 0}, + {"innodb-force-recovery", OPT_INNODB_FORCE_RECOVERY, + "This option starts up the embedded InnoDB instance in crash " + "recovery mode to ignore page corruption; should be used " + "with the \"--apply-log\" option, in emergencies only. The " + "default value is 0. Refer to \"innodb_force_recovery\" server " + "system variable documentation for more details.", + (uchar*)&xtrabackup_innodb_force_recovery, + (uchar*)&xtrabackup_innodb_force_recovery, + 0, GET_ULONG, OPT_ARG, 0, 0, SRV_FORCE_IGNORE_CORRUPT, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -669,6 +680,7 @@ innobackupex [--compress] [--compress-threads=NUMBER-OF-THREADS] [--compress-chu innobackupex --apply-log [--use-memory=B]\n\ [--defaults-file=MY.CNF]\n\ [--export] [--ibbackup=IBBACKUP-BINARY]\n\ + [--innodb-force-recovery=1]\n\ BACKUP-DIR\n\ \n\ innobackupex --copy-back [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME] BACKUP-DIR\n\ diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index ffb09c73edb..59551a7d044 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -271,6 +271,12 @@ static char *xtrabackup_debug_sync = NULL; my_bool xtrabackup_incremental_force_scan = FALSE; +/* + * Ignore corrupt pages (disabled by default; used + * by "innobackupex" as a command line argument). + */ +ulong xtrabackup_innodb_force_recovery = 0; + /* The flushed lsn which is read from data files */ lsn_t flushed_lsn= 0; @@ -1046,7 +1052,8 @@ enum options_xtrabackup OPT_ROCKSDB_DATADIR, OPT_BACKUP_ROCKSDB, OPT_XTRA_CHECK_PRIVILEGES, - OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION + OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION, + OPT_INNODB_FORCE_RECOVERY }; struct my_option xb_client_options[]= { @@ -1677,6 +1684,13 @@ struct my_option xb_server_options[] = &opt_check_privileges, &opt_check_privileges, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY, + "(for --prepare): Crash recovery mode (ignores " + "page corruption; for emergencies only).", + (G_PTR*)&srv_force_recovery, + (G_PTR*)&srv_force_recovery, + 0, GET_ULONG, OPT_ARG, 0, 0, SRV_FORCE_IGNORE_CORRUPT, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1808,24 +1822,26 @@ static int prepare_export() " --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" - " --console --skip-log-error --skip-log-bin --bootstrap < " + " --console --skip-log-error --skip-log-bin --bootstrap %s < " BOOTSTRAP_FILENAME IF_WIN("\"",""), - mariabackup_exe, + mariabackup_exe, orig_argv1, (my_defaults_group_suffix?my_defaults_group_suffix:""), - xtrabackup_use_memory); + xtrabackup_use_memory, + (srv_force_recovery ? "--innodb-force-recovery=1" : "")); } else { - sprintf(cmdline, + snprintf(cmdline, sizeof cmdline, IF_WIN("\"","") "\"%s\" --mysqld" " --defaults-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" - " --console --log-error= --skip-log-bin --bootstrap < " + " --console --log-error= --skip-log-bin --bootstrap %s < " BOOTSTRAP_FILENAME IF_WIN("\"",""), mariabackup_exe, (my_defaults_group_suffix?my_defaults_group_suffix:""), - xtrabackup_use_memory); + xtrabackup_use_memory, + (srv_force_recovery ? "--innodb-force-recovery=1" : "")); } msg("Prepare export : executing %s\n", cmdline); @@ -1985,6 +2001,13 @@ xb_get_one_option(int optid, ADD_PRINT_PARAM_OPT(innobase_buffer_pool_filename); break; + case OPT_INNODB_FORCE_RECOVERY: + + if (srv_force_recovery) { + ADD_PRINT_PARAM_OPT(srv_force_recovery); + } + break; + case OPT_XTRA_TARGET_DIR: strmake(xtrabackup_real_target_dir,argument, sizeof(xtrabackup_real_target_dir)-1); xtrabackup_target_dir= xtrabackup_real_target_dir; @@ -2250,6 +2273,29 @@ innodb_init_param(void) srv_undo_dir = (char*) "."; } + compile_time_assert(SRV_FORCE_IGNORE_CORRUPT == 1); + + /* + * This option can be read both from the command line, and the + * defaults file. The assignment should account for both cases, + * and for "--innobackupex". Since the command line argument is + * parsed after the defaults file, it takes precedence. + */ + if (xtrabackup_innodb_force_recovery) { + srv_force_recovery = xtrabackup_innodb_force_recovery; + } + + if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) { + if (!xtrabackup_prepare) { + msg("mariabackup: The option \"innodb_force_recovery\"" + " should only be used with \"%s\".", + (innobackupex_mode ? "--apply-log" : "--prepare")); + goto error; + } else { + msg("innodb_force_recovery = %lu", srv_force_recovery); + } + } + return(FALSE); error: diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index 15d53d00db4..e2955f58d6a 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -172,6 +172,8 @@ enum binlog_info_enum { BINLOG_INFO_OFF, BINLOG_INFO_ON, extern ulong opt_binlog_info; +extern ulong xtrabackup_innodb_force_recovery; + void xtrabackup_io_throttling(void); my_bool xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info); diff --git a/mysql-test/suite/mariabackup/innodb_force_recovery.result b/mysql-test/suite/mariabackup/innodb_force_recovery.result new file mode 100644 index 00000000000..94a265cfabe --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_force_recovery.result @@ -0,0 +1,26 @@ +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); +# "innodb_force_recovery=1" should be allowed with "--prepare" only (mariabackup) +FOUND 1 /should only be used with "--prepare"/ in backup.log +# "innodb_force_recovery=1" should be allowed with "--apply-log" only (innobackupex) +FOUND 1 /should only be used with "--apply-log"/ in backup.log +# "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (mariabackup) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (innobackupex) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" should be read from "backup-my.cnf" (mariabackup) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery=1" should be read from "backup-my.cnf" (innobackupex) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" from the command line should override "backup-my.cnf" (mariabackup) +NOT FOUND /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" from the command line should override "backup-my.cnf" (innobackupex) +NOT FOUND /innodb_force_recovery = 1/ in backup.log +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT * FROM t; +i +1 +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/innodb_force_recovery.test b/mysql-test/suite/mariabackup/innodb_force_recovery.test new file mode 100644 index 00000000000..3a7b3c6106c --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_force_recovery.test @@ -0,0 +1,138 @@ +# This test checks if "innodb_force_recovery" is only allowed with "--prepare" +# (for mariabackup) and "--apply-log" (for innobackupex), and is limited to +# "SRV_FORCE_IGNORE_CORRUPT" only. + +# Setup. +--source include/have_innodb.inc + +--let targetdir=$MYSQLTEST_VARDIR/tmp/backup +--let backuplog=$MYSQLTEST_VARDIR/tmp/backup.log + +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); + +# Check for command line arguments. +--echo # "innodb_force_recovery=1" should be allowed with "--prepare" only (mariabackup) +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --innodb-force-recovery=1 --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=should only be used with "--prepare" +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc + +--echo # "innodb_force_recovery=1" should be allowed with "--apply-log" only (innobackupex) +--disable_result_log +--error 1 +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp --innodb-force-recovery=1 $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=should only be used with "--apply-log" +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +--echo # "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (mariabackup) +--disable_result_log +exec $XTRABACKUP --prepare --innodb-force-recovery=2 --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; +--enable_result_log +--echo # "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (innobackupex) +--disable_result_log +exec $XTRABACKUP --innobackupex --apply-log --innodb-force-recovery=2 $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +# Check for default file ("backup-my.cnf"). +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=1\n"; +close $fd; +EOF +--echo # "innodb_force_recovery" should be read from "backup-my.cnf" (mariabackup) +--disable_result_log +exec $XTRABACKUP --defaults-file=$targetdir/backup-my.cnf --prepare --export --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=2\n"; +close $fd; +EOF +--echo # "innodb_force_recovery=1" should be read from "backup-my.cnf" (innobackupex) +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$targetdir/backup-my.cnf --apply-log --export $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +# Check for command line argument precedence. +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=1\n"; +close $fd; +EOF +--echo # "innodb_force_recovery" from the command line should override "backup-my.cnf" (mariabackup) +--disable_result_log +exec $XTRABACKUP --defaults-file=$targetdir/backup-my.cnf --prepare --innodb-force-recovery=0 --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=2\n"; +close $fd; +EOF +--echo # "innodb_force_recovery" from the command line should override "backup-my.cnf" (innobackupex) +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$targetdir/backup-my.cnf --apply-log --innodb-force-recovery=0 --export $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc + +--source include/restart_and_restore.inc + +# Check for restore. +SELECT * FROM t; + +# Clean-up. +DROP TABLE t; +--rmdir $targetdir +--remove_file $backuplog diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a7be1cdbf21..9548730b359 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2322,7 +2322,7 @@ files_checked: to the data files and truncate or delete the log. Unless --export is specified, no further change to InnoDB files is needed. */ - ut_ad(!srv_force_recovery); + ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT); ut_ad(srv_n_log_files_found <= 1); ut_ad(recv_no_log_write); buf_flush_sync_all_buf_pools(); From 4c80dcda46e4183df00f9fdb35ed08975e55e8f8 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Thu, 1 Apr 2021 16:49:07 +0300 Subject: [PATCH 10/35] fix gcc optimized build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../sql/spatial.cc: In member function ‘double Gis_point::calculate_haversine(const Geometry*, double, int*)’: ../sql/spatial.cc:1093:45: error: ‘y1r’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 1093 | res= 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong))); | ~~~^~~~~ ../sql/spatial.cc:1092:20: error: ‘x1r’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 1092 | dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2); | ~~~~~^~~~~~ ../sql/spatial.cc:1093:54: error: ‘y2r’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 1093 | res= 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong))); | ~~~^~~~~ ../sql/spatial.cc:1092:20: error: ‘x2r’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 1092 | dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2); | ~~~~~^~~~~~ c --- sql/spatial.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/spatial.cc b/sql/spatial.cc index 2482a21bb5f..319c1aaaef6 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -1050,7 +1050,7 @@ double Gis_point::calculate_haversine(const Geometry *g, int *error) { DBUG_ASSERT(sphere_radius > 0); - double x1r, x2r, y1r, y2r, dlong, dlat, res; + double x1r= 0.0, x2r= 0.0, y1r= 0.0, y2r= 0.0, dlong, dlat, res; // This check is done only for optimization purposes where we know it will // be one and only one point in Multipoint From fb9d151934c3444e55eb3ea505e2403d082c9a85 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Thu, 1 Apr 2021 21:47:30 +0200 Subject: [PATCH 11/35] MDEV-25321: mariabackup failed if password is passed via environment variable The mariabackup interface currently supports passing a password through an explicit command line variable, but does not support passing a password through the MYSQL_PWD environment variable. At the same time, the Galera SST script for mariabackup uses the environment variable to pass the password, which leads (in some cases) to an unsuccessful launch of mariabackup and to the inability to start the cluster. This patch fixes this issue. It does not need a separate test, as the problem is visible in general testing on buildbot. --- extra/mariabackup/innobackupex.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index fefd81dc1be..5bc320264e4 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -41,6 +41,7 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include +#include #include #include #include @@ -904,6 +905,12 @@ ibx_init() opt_user = opt_ibx_user; opt_password = opt_ibx_password; +#if !defined(DONT_USE_MYSQL_PWD) + if (!opt_password) + { + opt_password=getenv("MYSQL_PWD"); + } +#endif opt_host = opt_ibx_host; opt_defaults_group = opt_ibx_defaults_group; opt_socket = opt_ibx_socket; From 6fe624b5acf51383d39eb0e547a03779d41cf4a8 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 3 Apr 2021 12:12:15 +0200 Subject: [PATCH 12/35] MDEV-25242 Server crashes in check_grant upon invoking function with userstat enabled also fix index_stats table. followup for 5a798071199 --- mysql-test/r/userstat.result | 2 ++ mysql-test/t/userstat.test | 2 ++ plugin/userstat/index_stats.cc | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/userstat.result b/mysql-test/r/userstat.result index 804d5451252..8aad76c3750 100644 --- a/mysql-test/r/userstat.result +++ b/mysql-test/r/userstat.result @@ -240,6 +240,8 @@ create function f() returns int return (select 1 from performance_schema.threads set global userstat= 1; select f() from information_schema.table_statistics; ERROR 21000: Subquery returns more than 1 row +select f() from information_schema.index_statistics; +ERROR 21000: Subquery returns more than 1 row set global userstat= 0; drop function f; # diff --git a/mysql-test/t/userstat.test b/mysql-test/t/userstat.test index cc7ddd58e11..6d486810db1 100644 --- a/mysql-test/t/userstat.test +++ b/mysql-test/t/userstat.test @@ -121,6 +121,8 @@ create function f() returns int return (select 1 from performance_schema.threads set global userstat= 1; --error ER_SUBQUERY_NO_1_ROW select f() from information_schema.table_statistics; +--error ER_SUBQUERY_NO_1_ROW +select f() from information_schema.index_statistics; set global userstat= 0; drop function f; diff --git a/plugin/userstat/index_stats.cc b/plugin/userstat/index_stats.cc index 87e6da63e38..1a7b0bbfcbd 100644 --- a/plugin/userstat/index_stats.cc +++ b/plugin/userstat/index_stats.cc @@ -26,7 +26,7 @@ static int index_stats_fill(THD *thd, TABLE_LIST *tables, COND *cond) tmp_table.grant.privilege= 0; if (check_access(thd, SELECT_ACL, tmp_table.db, &tmp_table.grant.privilege, NULL, 0, 1) || - check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, 1)) + check_grant(thd, SELECT_ACL, &tmp_table, 1, 1, 1)) continue; index_name= strend(tmp_table.table_name)+1; From c32edd75155129fbfe353aed6402374d40e63b65 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 6 Apr 2021 18:51:41 +0530 Subject: [PATCH 13/35] MDEV-25295 Aborted FTS_DOC_ID_INDEX considered as existing FTS_DOC_ID_INDEX during DDL InnoDB should skip the dropped aborted FTS_DOC_ID_INDEX while checking the existing FTS_DOC_ID_INDEX in the table. InnoDB should able to create new FTS_DOC_ID_INDEX if the fulltext index is being added for the first time. --- mysql-test/suite/innodb_fts/r/fulltext.result | 13 +++++++++++++ mysql-test/suite/innodb_fts/t/fulltext.test | 14 ++++++++++++++ storage/innobase/handler/handler0alter.cc | 6 ++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_fts/r/fulltext.result b/mysql-test/suite/innodb_fts/r/fulltext.result index 42e294b3293..90deb48a223 100644 --- a/mysql-test/suite/innodb_fts/r/fulltext.result +++ b/mysql-test/suite/innodb_fts/r/fulltext.result @@ -691,3 +691,16 @@ FTS_DOC_ID t 2 foo bar 3 foo DROP TABLE t; +# +# MDEV-25295 Aborted FTS_DOC_ID_INDEX considered as +# existing FTS_DOC_ID_INDEX during DDL +# +SET sql_mode=''; +CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED NOT NULL,title CHAR(1),body TEXT)engine=innodb; +INSERT INTO t1 (FTS_DOC_ID,title,body)VALUES(1,0,0), (1,0,0); +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +DROP TABLE t1; +SET sql_mode = DEFAULT; diff --git a/mysql-test/suite/innodb_fts/t/fulltext.test b/mysql-test/suite/innodb_fts/t/fulltext.test index 663b202265b..1533c573ebf 100644 --- a/mysql-test/suite/innodb_fts/t/fulltext.test +++ b/mysql-test/suite/innodb_fts/t/fulltext.test @@ -717,3 +717,17 @@ while ($N) } DROP TABLE t; + +--echo # +--echo # MDEV-25295 Aborted FTS_DOC_ID_INDEX considered as +--echo # existing FTS_DOC_ID_INDEX during DDL +--echo # +SET sql_mode=''; +CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED NOT NULL,title CHAR(1),body TEXT)engine=innodb; +INSERT INTO t1 (FTS_DOC_ID,title,body)VALUES(1,0,0), (1,0,0); +--error ER_DUP_ENTRY +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +--error ER_DUP_ENTRY +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +DROP TABLE t1; +SET sql_mode = DEFAULT; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index e03621795ba..ccc3fe3b921 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2404,9 +2404,11 @@ innobase_fts_check_doc_id_index( for (index = dict_table_get_first_index(table); index; index = dict_table_get_next_index(index)) { + /* Check if there exists a unique index with the name of - FTS_DOC_ID_INDEX_NAME */ - if (innobase_strcasecmp(index->name, FTS_DOC_ID_INDEX_NAME)) { + FTS_DOC_ID_INDEX_NAME and ignore the corrupted index */ + if (index->type & DICT_CORRUPT + || innobase_strcasecmp(index->name, FTS_DOC_ID_INDEX_NAME)) { continue; } From 82a2ea64b47ba7d4f10019418f84a0f3131d1c11 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Fri, 19 Mar 2021 17:11:04 +0700 Subject: [PATCH 14/35] Fix postinst trigger when systemd is not running (Closes: #983563) Checking for the existence of the systemctl command only tells us that systemd is installed, however it does not tell us if systemd is running. What we really want to do here is reload systemd if it's installed AND if it's running. The usual way to check if systemd is running is to check for the existence of '/run/systemd/system'. Why would systemd be installed but not running? This is something that happens when one sets up or upgrade a system in a chroot or container. For more details refer to the bug report: Closes PR #1787 --- debian/mariadb-server-10.2.postinst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/mariadb-server-10.2.postinst b/debian/mariadb-server-10.2.postinst index 063f0d8c58b..057b1bf540e 100644 --- a/debian/mariadb-server-10.2.postinst +++ b/debian/mariadb-server-10.2.postinst @@ -247,8 +247,8 @@ EOF ;; triggered) - if [ -x "$(command -v systemctl)" ]; then - systemctl daemon-reload + if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload fi invoke restart ;; From 72da83ff99860878fc28a1f26bfd893baa153368 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 30 Mar 2021 18:42:28 +0530 Subject: [PATCH 15/35] MDEV-25019 memory allocation failures during startup because server failure in different, confusing ways InnoDB fails to free the buffer pool instance mutex and zip mutex If the allocation of buffer pool instance chunk fails. So it leads to freeing of buffer pool before freeing the mutexes and leads to double freeing of memory while freeing the mutex during shutdown. --- .../suite/innodb/r/innodb_buffer_pool_fail.result | 7 +++++++ .../suite/innodb/t/innodb_buffer_pool_fail.test | 11 +++++++++++ storage/innobase/buf/buf0buf.cc | 4 ++++ 3 files changed, 22 insertions(+) create mode 100644 mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result create mode 100644 mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result new file mode 100644 index 00000000000..9f6959cb993 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result @@ -0,0 +1,7 @@ +call mtr.add_suppression("InnoDB: Cannot allocate memory for the buffer pool"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted at srv0start.cc.*"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); +# +# MDEV-25019 memory allocation failures during startup cause server failure in different, confusing ways +# diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test new file mode 100644 index 00000000000..1d938e12e78 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test @@ -0,0 +1,11 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +call mtr.add_suppression("InnoDB: Cannot allocate memory for the buffer pool"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted at srv0start.cc.*"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); +--echo # +--echo # MDEV-25019 memory allocation failures during startup cause server failure in different, confusing ways +--echo # +let restart_parameters=--debug_dbug="+d,ib_buf_chunk_init_fails"; +--source include/restart_mysqld.inc diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 9f3d743ada1..070789288b6 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1864,6 +1864,10 @@ buf_pool_init_instance( ut_free(buf_pool->chunks); buf_pool_mutex_exit(buf_pool); + /* InnoDB should free the mutex which was + created so far before freeing the instance */ + mutex_free(&buf_pool->mutex); + mutex_free(&buf_pool->zip_mutex); return(DB_ERROR); } From c6d0531cad096e6b85ee34209f1b083e6f77a42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 8 Apr 2021 09:46:56 +0300 Subject: [PATCH 16/35] MDEV-13467 fixup: Improve error handling --- sql/spatial.cc | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/sql/spatial.cc b/sql/spatial.cc index 711efa91394..7bb3ecff948 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. - Copyright (c) 2011, 2013, Monty Program Ab. + Copyright (c) 2011, 2020, 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 @@ -1050,7 +1050,7 @@ double Gis_point::calculate_haversine(const Geometry *g, int *error) { DBUG_ASSERT(sphere_radius > 0); - double x1r, x2r, y1r, y2r, dlong, dlat, res; + double x1r, x2r, y1r, y2r; // This check is done only for optimization purposes where we know it will // be one and only one point in Multipoint @@ -1067,31 +1067,39 @@ double Gis_point::calculate_haversine(const Geometry *g, Geometry *gg= Geometry::construct(&gbuff, point_temp, point_size-1); DBUG_ASSERT(gg); if (static_cast(gg)->get_xy_radian(&x2r, &y2r)) + { DBUG_ASSERT(0); + return -1; + } } else { if (static_cast(g)->get_xy_radian(&x2r, &y2r)) + { DBUG_ASSERT(0); + return -1; + } } if (this->get_xy_radian(&x1r, &y1r)) + { DBUG_ASSERT(0); + return -1; + } // Check boundary conditions: longitude[-180,180] if (!((x2r >= -M_PI && x2r <= M_PI) && (x1r >= -M_PI && x1r <= M_PI))) { *error=1; return -1; } - // Check boundary conditions: lattitude[-90,90] + // Check boundary conditions: latitude[-90,90] if (!((y2r >= -M_PI/2 && y2r <= M_PI/2) && (y1r >= -M_PI/2 && y1r <= M_PI/2))) { *error=-1; return -1; } - dlat= sin((y2r - y1r)/2)*sin((y2r - y1r)/2); - dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2); - res= 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong))); - return res; + double dlat= sin((y2r - y1r)/2)*sin((y2r - y1r)/2); + double dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2); + return 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong))); } From 5a3151bcda2f279091a1e2f049a7d11cd91065d6 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 9 Apr 2021 12:01:42 +0530 Subject: [PATCH 17/35] Improve diagnostics in order to catch MDEV-18868 and similar bugs --- storage/innobase/fts/fts0fts.cc | 18 ++++++++++++------ storage/innobase/include/btr0bulk.h | 2 ++ storage/innobase/row/row0ftsort.cc | 6 ++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 1bdfbddca04..a74b5083128 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2546,7 +2546,8 @@ fts_get_max_cache_size( } } else { ib::error() << "(" << error << ") reading max" - " cache config value from config table"; + " cache config value from config table " + << fts_table->table->name; } ut_free(value.f_str); @@ -2719,7 +2720,8 @@ func_exit: } else { *doc_id = 0; - ib::error() << "(" << error << ") while getting next doc id."; + ib::error() << "(" << error << ") while getting next doc id " + "for table " << table->name; fts_sql_rollback(trx); if (error == DB_DEADLOCK) { @@ -2799,7 +2801,8 @@ fts_update_sync_doc_id( cache->synced_doc_id = doc_id; } else { ib::error() << "(" << error << ") while" - " updating last doc id."; + " updating last doc id for table" + << table->name; fts_sql_rollback(trx); } @@ -4044,7 +4047,8 @@ fts_sync_write_words( if (UNIV_UNLIKELY(error != DB_SUCCESS) && !print_error) { ib::error() << "(" << error << ") writing" - " word node to FTS auxiliary index table."; + " word node to FTS auxiliary index table " + << table->name; print_error = TRUE; } } @@ -4199,7 +4203,8 @@ fts_sync_commit( fts_sql_commit(trx); } else { fts_sql_rollback(trx); - ib::error() << "(" << error << ") during SYNC."; + ib::error() << "(" << error << ") during SYNC of " + "table " << sync->table->name; } if (UNIV_UNLIKELY(fts_enable_diag_print) && elapsed_time) { @@ -4970,7 +4975,8 @@ fts_get_rows_count( trx->error_state = DB_SUCCESS; } else { ib::error() << "(" << error - << ") while reading FTS table."; + << ") while reading FTS table " + << table_name; break; /* Exit the loop. */ } diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index 854414d504d..6687d29593a 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -326,6 +326,8 @@ public: /** Re-latch all latches */ void latch(); + dict_index_t* index() { return m_index; } + private: /** Insert a tuple to a page in a level @param[in] tuple tuple to insert diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 4085ff17bd3..39b31c153ad 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -924,7 +924,7 @@ loop: << " records, the sort queue has " << UT_LIST_GET_LEN(psort_info->fts_doc_list) << " records. But sort cannot get the next" - " records"; + " records during alter table " << table->name; goto exit; } } else if (psort_info->state == FTS_PARENT_EXITING) { @@ -1220,7 +1220,9 @@ row_merge_write_fts_word( if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Failed to write word to FTS auxiliary" - " index table, error " << error; + " index table " + << ins_ctx->btr_bulk->index()->table->name + << ", error " << error; ret = error; } From 1ac4d0c168c3d438752e3a72c79d29a6cbd5a127 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 9 Apr 2021 17:38:21 +0530 Subject: [PATCH 18/35] BtrBulk::table_name(): Return the table name while displaying table name for fts diagnostics --- storage/innobase/include/btr0bulk.h | 2 +- storage/innobase/row/row0ftsort.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index 6687d29593a..911a2726422 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -326,7 +326,7 @@ public: /** Re-latch all latches */ void latch(); - dict_index_t* index() { return m_index; } + table_name_t table_name() { return m_index->table->name; } private: /** Insert a tuple to a page in a level diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 39b31c153ad..2ca930e0934 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1221,7 +1221,7 @@ row_merge_write_fts_word( if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Failed to write word to FTS auxiliary" " index table " - << ins_ctx->btr_bulk->index()->table->name + << ins_ctx->btr_bulk->table_name() << ", error " << error; ret = error; } From 8ff0ac45dcc909688c50d93f7575e2084433df30 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 7 Apr 2021 16:44:30 +0200 Subject: [PATCH 19/35] MDEV-25328: --innodb command line option causes mariabackup to fail This patch fixes an issue with launching mariabackup during SST (when used with Galera), when during bootstrap mariabackup receives the "--innodb" option, which is incorrectly interpreted as shortcut for "--innodb-force-recovery". This patch does not require separate test for mtr, as the problem is visible in general testing on buildbot. --- extra/mariabackup/xtrabackup.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 59551a7d044..0743c8224b0 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -6622,6 +6622,8 @@ int main(int argc, char **argv) { char **client_defaults, **server_defaults; + my_getopt_prefix_matching= 0; + if (get_exepath(mariabackup_exe,FN_REFLEN, argv[0])) strncpy(mariabackup_exe,argv[0], FN_REFLEN-1); From d5dacca4c5a631b81426c8ca559a54c97487fcbb Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 7 Apr 2021 16:49:10 +0200 Subject: [PATCH 20/35] Clarified abbreviated option names in some tests, to avoid problems with ambiguous options in the future. --- mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test | 2 +- mysql-test/t/mysqldump-nl.test | 8 ++++---- mysql-test/t/parser_not_embedded.test | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test index 5bdd1ff8b6b..a594b7c2a61 100644 --- a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test +++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test @@ -329,7 +329,7 @@ while($ntables) -- echo ### detect failure. Before the patch mysqlbinlog would find -- echo ### a corrupted event, thence would fail. -- let $MYSQLD_DATADIR= `SELECT @@datadir` --- exec $MYSQL_BINLOG -v --hex $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +-- exec $MYSQL_BINLOG -v --hexdump $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog ## clean up ## For debugging purposes you might want not to remove these diff --git a/mysql-test/t/mysqldump-nl.test b/mysql-test/t/mysqldump-nl.test index 863c846b9a6..4451b0605c2 100644 --- a/mysql-test/t/mysqldump-nl.test +++ b/mysql-test/t/mysqldump-nl.test @@ -26,10 +26,10 @@ create procedure sp() select * from `v1 flush tables; use test; -exec $MYSQL_DUMP --compact --comment --routines --add-drop-database --databases 'mysqltest1 +exec $MYSQL_DUMP --compact --comments --routines --add-drop-database --databases 'mysqltest1 1tsetlqsym'; -exec $MYSQL_DUMP --compact --comment --routines --add-drop-database --databases 'mysqltest1 +exec $MYSQL_DUMP --compact --comments --routines --add-drop-database --databases 'mysqltest1 1tsetlqsym' | $MYSQL; show tables from `mysqltest1 @@ -45,11 +45,11 @@ create database `test\`` show databases like 'test%'; -exec $MYSQL_DUMP --compact --comment --add-drop-database --databases 'test`' 'test\` +exec $MYSQL_DUMP --compact --comments --add-drop-database --databases 'test`' 'test\` \! ls #'; -exec $MYSQL_DUMP --compact --comment --add-drop-database --databases 'test`' 'test\` +exec $MYSQL_DUMP --compact --comments --add-drop-database --databases 'test`' 'test\` \! ls #' | $MYSQL; diff --git a/mysql-test/t/parser_not_embedded.test b/mysql-test/t/parser_not_embedded.test index 3ebd23e888e..3af1260f4ad 100644 --- a/mysql-test/t/parser_not_embedded.test +++ b/mysql-test/t/parser_not_embedded.test @@ -21,7 +21,7 @@ select 7 as expected, /*!01000 1 + /*!01000 8 + /*!01000 error */ 16 + */ 2 + */ select 4 as expected, /* 1 + /*!01000 8 + */ 2 + */ 4; EOF ---exec $MYSQL --comment --force --table test <$MYSQLTEST_VARDIR/tmp/bug39559.sql +--exec $MYSQL --comments --force --table test <$MYSQLTEST_VARDIR/tmp/bug39559.sql --remove_file $MYSQLTEST_VARDIR/tmp/bug39559.sql --echo # Bug#46527 "COMMIT AND CHAIN RELEASE does not make sense" From bf1e09e0c472600165887b6ad52b993a00394f5a Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 7 Apr 2021 16:53:23 +0200 Subject: [PATCH 21/35] Removed extra spaces in generated command lines (minor "cosmetic" change after MDEV-24197) --- extra/mariabackup/xtrabackup.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 0743c8224b0..d4e7114f635 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1815,33 +1815,33 @@ static int prepare_export() // Process defaults-file , it can have some --lc-language stuff, // which is* unfortunately* still necessary to get mysqld up - if (strncmp(orig_argv1,"--defaults-file=",16) == 0) + if (strncmp(orig_argv1,"--defaults-file=", 16) == 0) { snprintf(cmdline, sizeof cmdline, - IF_WIN("\"","") "\"%s\" --mysqld \"%s\" " + IF_WIN("\"","") "\"%s\" --mysqld \"%s\"" " --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" - " --console --skip-log-error --skip-log-bin --bootstrap %s < " + " --console --skip-log-error --skip-log-bin --bootstrap %s< " BOOTSTRAP_FILENAME IF_WIN("\"",""), mariabackup_exe, orig_argv1, (my_defaults_group_suffix?my_defaults_group_suffix:""), xtrabackup_use_memory, - (srv_force_recovery ? "--innodb-force-recovery=1" : "")); + (srv_force_recovery ? "--innodb-force-recovery=1 " : "")); } else { snprintf(cmdline, sizeof cmdline, - IF_WIN("\"","") "\"%s\" --mysqld" + IF_WIN("\"","") "\"%s\" --mysqld" " --defaults-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" - " --console --log-error= --skip-log-bin --bootstrap %s < " + " --console --log-error= --skip-log-bin --bootstrap %s< " BOOTSTRAP_FILENAME IF_WIN("\"",""), mariabackup_exe, (my_defaults_group_suffix?my_defaults_group_suffix:""), xtrabackup_use_memory, - (srv_force_recovery ? "--innodb-force-recovery=1" : "")); + (srv_force_recovery ? "--innodb-force-recovery=1 " : "")); } msg("Prepare export : executing %s\n", cmdline); From 3eecb8db227173284aff8c457dea3c8009117a72 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sun, 11 Apr 2021 17:07:36 +0200 Subject: [PATCH 22/35] MDEV-25356: SST scripts should use the new mariabackup interface SST scripts for Galera should use the new mariabackup interface instead of the innobackupex interface, which is currently only supported for compatibility reasons. This commit converts the SST script for mariabackup to use the new interface. It does not need separate tests, as any problems will be seen as failures when running multiple tests for the mariabackup-based SST. --- extra/mariabackup/backup_mysql.cc | 8 ++++++++ extra/mariabackup/innobackupex.cc | 7 ------- scripts/wsrep_sst_mariabackup.sh | 14 +++++++------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index 1d7242c5c75..824b8b6d5f3 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -44,6 +44,7 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include #include +#include #include #include #include "common.h" @@ -107,6 +108,13 @@ xb_mysql_connect() return(NULL); } +#if !defined(DONT_USE_MYSQL_PWD) + if (!opt_password) + { + opt_password=getenv("MYSQL_PWD"); + } +#endif + if (!opt_secure_auth) { mysql_options(connection, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth); diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index 5bc320264e4..fefd81dc1be 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -41,7 +41,6 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include -#include #include #include #include @@ -905,12 +904,6 @@ ibx_init() opt_user = opt_ibx_user; opt_password = opt_ibx_password; -#if !defined(DONT_USE_MYSQL_PWD) - if (!opt_password) - { - opt_password=getenv("MYSQL_PWD"); - } -#endif opt_host = opt_ibx_host; opt_defaults_group = opt_ibx_defaults_group; opt_socket = opt_ibx_socket; diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 4354e341ca5..29c527d8ff3 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -766,9 +766,9 @@ if [[ $ssyslog -eq 1 ]];then logger -p daemon.info -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" } - INNOAPPLY="${INNOBACKUPEX_BIN} --innobackupex $disver $iapts \$INNOEXTRA --apply-log \$rebuildcmd \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply" - INNOMOVE="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move" - INNOBACKUP="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" + INNOAPPLY="${INNOBACKUPEX_BIN} --prepare $disver $iapts \$INNOEXTRA $rebuildcmd --target-dir=\${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply" + INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --move-back $disver $impts --force-non-empty-directories --target-dir=\${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move" + INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --backup $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt --target-dir=\$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" fi else @@ -830,9 +830,9 @@ then fi - INNOAPPLY="${INNOBACKUPEX_BIN} --innobackupex $disver $iapts \$INNOEXTRA --apply-log \$rebuildcmd \${DATA} &> ${INNOAPPLYLOG}" - INNOMOVE="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &> ${INNOMOVELOG}" - INNOBACKUP="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> ${INNOBACKUPLOG}" + INNOAPPLY="${INNOBACKUPEX_BIN} --prepare $disver $iapts \$INNOEXTRA $rebuildcmd --target-dir=\${DATA} &> ${INNOAPPLYLOG}" + INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --move-back $disver $impts --force-non-empty-directories --target-dir=\${DATA} &> ${INNOMOVELOG}" + INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --backup $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt --target-dir=\$itmpdir 2> ${INNOBACKUPLOG}" fi get_stream @@ -855,7 +855,7 @@ then -z $(parse_cnf --mysqld tmpdir "") && \ -z $(parse_cnf xtrabackup tmpdir "") ]]; then xtmpdir=$(mktemp -d) - tmpopts=" --tmpdir=$xtmpdir" + tmpopts="--tmpdir=$xtmpdir" wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" fi From 966c5a35af0a84ea147f754f6eb0cc1fd0a5826f Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Thu, 1 Apr 2021 07:01:11 +0200 Subject: [PATCH 23/35] MDEV-25307: The value of the auto-increment variables changes during the test The auto-increment variables may change intermittently during the execution of some tests from the Galera mtr suite, causing these tests to fail. This patch creates conditions in which unpredictable changes to these variables are not possible during the execution of those tests in which this problem is noticed or their values are restored before the end of testing. --- mysql-test/suite/galera/disabled.def | 1 - mysql-test/suite/galera/r/galera_var_sst_auth.result | 2 ++ mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.cnf | 7 +++++++ mysql-test/suite/galera/t/galera_var_sst_auth.cnf | 5 ----- mysql-test/suite/galera/t/galera_var_sst_auth.test | 8 +++++++- 5 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.cnf diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index a72c84564f0..6285da7b11c 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -14,7 +14,6 @@ MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-329 : MDEV-19962 Galera test failure on MW-329 galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() -galera_binlog_stmt_autoinc : MDEV-19959 Galera test failure on galera_binlog_stmt_autoinc galera_concurrent_ctas : MDEV-24842 Galera test failure on galera_concurrent_ctas galera_gcache_recover_manytrx : MDEV-18834 Galera test failure galera_mdl_race : MDEV-21524: galera.galera_mdl_race MTR failed: query 'reap' succeeded - should have failed with errno 1213 diff --git a/mysql-test/suite/galera/r/galera_var_sst_auth.result b/mysql-test/suite/galera/r/galera_var_sst_auth.result index 89a27dce4f6..e03576175c5 100644 --- a/mysql-test/suite/galera/r/galera_var_sst_auth.result +++ b/mysql-test/suite/galera/r/galera_var_sst_auth.result @@ -1,3 +1,5 @@ +connection node_1; +connection node_2; SELECT @@global.wsrep_sst_auth; @@global.wsrep_sst_auth ******** diff --git a/mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.cnf b/mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.cnf new file mode 100644 index 00000000000..889c81b4a0a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +auto_increment_offset=1 + +[mysqld.2] +auto_increment_offset=2 diff --git a/mysql-test/suite/galera/t/galera_var_sst_auth.cnf b/mysql-test/suite/galera/t/galera_var_sst_auth.cnf index ff29db2306b..114815d446a 100644 --- a/mysql-test/suite/galera/t/galera_var_sst_auth.cnf +++ b/mysql-test/suite/galera/t/galera_var_sst_auth.cnf @@ -5,8 +5,3 @@ wsrep_sst_auth=root: [mysqld.2] wsrep_sst_auth=root: - - - - - diff --git a/mysql-test/suite/galera/t/galera_var_sst_auth.test b/mysql-test/suite/galera/t/galera_var_sst_auth.test index ad7f46620ad..ebeaddc0e63 100644 --- a/mysql-test/suite/galera/t/galera_var_sst_auth.test +++ b/mysql-test/suite/galera/t/galera_var_sst_auth.test @@ -1,6 +1,11 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + # # MDEV-10492: Assertion failure on shutdown when wsrep_sst_auth set in config # @@ -30,4 +35,5 @@ SELECT @@global.wsrep_sst_auth; --source include/wait_condition.inc SELECT @@global.wsrep_sst_auth; - +# Restore original auto_increment_offset values. +--source include/auto_increment_offset_restore.inc From 058d93d47af79e650dc6a7abc107a400d8598e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Kek=C3=A4l=C3=A4inen?= Date: Sun, 11 Apr 2021 22:05:52 -0700 Subject: [PATCH 24/35] Deb: Stop depending on empty transitional package dh-systemd MariaDB Server still supports Ubuntu 16.04 "Xenial" until it goes EOL in April 30, 2021. Thus we need to include a customization for backwards compatibility. This change is intended to be applied for all MariaDB versions still supported, i.e. 10.2 to 10.6. --- debian/autobake-deb.sh | 9 +++++++++ debian/control | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index 5cf2398575a..21ab4d8fe22 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -106,6 +106,15 @@ then sed '/Package: mariadb-plugin-cassandra/,/^$/d' -i debian/control fi +# From Debian Stretch/Ubuntu Bionic onwards dh-systemd is just an empty +# transitional metapackage and the functionality was merged into debhelper. +# In Ubuntu Hirsute is was completely removed, so it can't be referenced anymore. +# Keep using it only on Debian Jessie and Ubuntu Xenial. +if apt-cache madison dh-systemd | grep 'dh-systemd' >/dev/null 2>&1 +then + sed 's/debhelper (>= 9.20160709~),/debhelper (>= 9), dh-systemd,/' -i debian/control +fi + # Adjust changelog, add new version echo "Incrementing changelog and starting build scripts" diff --git a/debian/control b/debian/control index ba6243c38dd..c906c1bd505 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,7 @@ Maintainer: MariaDB Developers Build-Depends: bison, chrpath, cmake (>= 2.7), - debhelper (>= 9), + debhelper (>= 9.20160709~), dh-apparmor, dh-systemd, dpatch, From 75dd7a048315affc0c5986b6e955965d46621c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 12 Apr 2021 10:53:08 +0300 Subject: [PATCH 25/35] MDEV-24434 Assertion trx->in_rw_trx_list... in trx_sys_any_active_transactions() trx_sys_any_active_transactions(): Remove a bogus debug assertion. In trx_commit_in_memory() and trx_erase_lists(), we will remove the transaction from trx_sys->rw_trx_list and set the state to TRX_STATE_COMMITTED_IN_MEMORY. --- storage/innobase/trx/trx0sys.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 8d00bd824a2..9138e9475bf 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, 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 @@ -997,11 +997,6 @@ trx_sys_any_active_transactions(void) /* This may count some ACTIVE transactions twice, both in rw_trx_list and mysql_trx_list. */ total_trx += trx->state == TRX_STATE_ACTIVE; - /* Any PREPARED or COMMITTED transactions must be - in rw_trx_list, so it suffices to count them there. */ - ut_ad(trx->in_rw_trx_list - || trx->state == TRX_STATE_NOT_STARTED - || trx->state == TRX_STATE_ACTIVE); trx_mutex_exit(trx); } From ea2d44d01b4aead2e1d6d88b9eede39fd99dff67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 12 Apr 2021 11:29:32 +0300 Subject: [PATCH 26/35] MDEV-18802 Assertion table->stat_initialized failed in dict_stats_update_if_needed() When a table has been evicted from dict_sys and reloaded internally by InnoDB for FOREIGN KEY processing, statistics may not be initialized, but nevertheless row_update_cascade_for_mysql() could invoke dict_stats_update_if_needed(). In that case, we cannot really update the statistics. For tables that have STATS_PERSISTENT=1 and STATS_AUTO_RECALC=1, ANALYZE TABLE might have to be executed later. dict_stats_update_if_needed(): Replace the assertion with a conditional early return. --- storage/innobase/dict/dict0stats_bg.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 589f53dde38..a4619a6069b 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2017, 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 @@ -154,9 +154,24 @@ schedule new estimates for table and index statistics to be calculated. void dict_stats_update_if_needed_func(dict_table_t *table) #endif { - ut_ad(table->stat_initialized); ut_ad(!mutex_own(&dict_sys->mutex)); + if (UNIV_UNLIKELY(!table->stat_initialized)) { + /* The table may have been evicted from dict_sys + and reloaded internally by InnoDB for FOREIGN KEY + processing, but not reloaded by the SQL layer. + + We can (re)compute the transient statistics when the + table is actually loaded by the SQL layer. + + Note: If InnoDB persistent statistics are enabled, + we will skip the updates. We must do this, because + dict_table_get_n_rows() below assumes that the + statistics have been initialized. The DBA may have + to execute ANALYZE TABLE. */ + return; + } + ulonglong counter = table->stat_modified_counter++; ulonglong n_rows = dict_table_get_n_rows(table); From cf2c6b7f8db9413e7c5e31e87bb5c799253d8d2e Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 9 Apr 2021 21:30:43 +0530 Subject: [PATCH 27/35] MDEV-24971 InnoDB access freed virtual column after rollback of secondary index Problem: ======== InnoDB fails to clean the index stub if it fails to add the virtual index which contains new virtual column. But it clears the newly virtual column from index in clear_added_indexes() during inplace_alter_table. On commit, InnoDB evicts and reload the table. In case of rollback, it doesn't happen. InnoDB clears the ABORTED index while opening the table or doing the DDL. In the mean time, InnoDB can access the dropped virtual index columns while creating prebuilt or rollback of concurrent DML. Solution: ========== (1) InnoDB should maintain newly added virtual column while rollbacking the newly added virtual index. (2) InnoDB must not defer the index removal if the alter table is executed with LOCK=EXCLUSIVE. (3) For LOCK=SHARED, InnoDB should check whether the table has any other transaction lock other than alter transaction before deferring the index stub. Replaced has_new_v_col with dict_add_vcol_info in dict_index_t to indicate whether the index has any new virtual column. dict_index_t::has_new_v_col(): Returns whether the index has newly added virtual column, it doesn't say which columns are newly added virtual column ha_innobase_inplace_ctx::is_new_vcol(): Return whether the given column is added as a part of the current alter. ha_innobase_inplace_ctx::clean_new_vcol_index(): Copy the newly added virtual column to new_vcol_info in dict_index_t. Replace the column in the index fields with virtual column stored in new_vcol_info. dict_index_t::assign_new_v_col(): Store the number of virtual column added in index as a part of alter table. dict_index_t::get_n_new_vcol(): Get the number of newly added virtual column dict_index_t::assign_drop_v_col(): Allocate the memory for adding new virtual column in new_vcol_info. dict_index_t::add_drop_v_col(): Add the newly added virtual column in new_vcol_info. dict_table_t::has_lock_for_other_trx(): Whether the table has any other transaction lock than given transaction. row_merge_drop_indexes(): Add parameter alter_trx and check whether the table has any other lock than alter transaction. --- .../suite/gcol/r/virtual_index_drop.result | 69 ++++++++++++++++ .../suite/gcol/t/virtual_index_drop.test | 71 ++++++++++++++++ storage/innobase/dict/dict0dict.cc | 2 +- storage/innobase/dict/dict0mem.cc | 2 +- storage/innobase/handler/handler0alter.cc | 75 ++++++++++++----- storage/innobase/include/dict0mem.h | 81 +++++++++++++++++-- storage/innobase/include/row0merge.h | 20 ++--- storage/innobase/row/row0merge.cc | 29 ++++--- storage/innobase/row/row0purge.cc | 2 +- 9 files changed, 300 insertions(+), 51 deletions(-) create mode 100644 mysql-test/suite/gcol/r/virtual_index_drop.result create mode 100644 mysql-test/suite/gcol/t/virtual_index_drop.test diff --git a/mysql-test/suite/gcol/r/virtual_index_drop.result b/mysql-test/suite/gcol/r/virtual_index_drop.result new file mode 100644 index 00000000000..012e61be459 --- /dev/null +++ b/mysql-test/suite/gcol/r/virtual_index_drop.result @@ -0,0 +1,69 @@ +# +# MDEV-24971 InnoDB access freed virtual column +# after rollback of secondary index +# +CREATE TABLE t1(f1 INT, f2 INT AS (f1 + 2) VIRTUAL)ENGINE=InnoDB; +INSERT INTO t1(f1) VALUES(1), (1); +ALTER TABLE t1 ADD UNIQUE INDEX(f2), ALGORITHM=INPLACE, LOCK=EXCLUSIVE; +ERROR 23000: Duplicate entry '3' for key 'f2' +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) GENERATED ALWAYS AS (`f1` + 2) VIRTUAL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT, f2 INT AS (f1 + 2) VIRTUAL)ENGINE=InnoDB; +INSERT INTO t1(f1) VALUES(1), (1); +ALTER TABLE t1 ADD UNIQUE INDEX(f2), ALGORITHM=INPLACE, LOCK=SHARED; +ERROR 23000: Duplicate entry '3' for key 'f2' +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) GENERATED ALWAYS AS (`f1` + 2) VIRTUAL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; +SET DEBUG_DBUG="+d,create_index_fail"; +SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; +ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3); +connect con1,localhost,root,,,; +SET DEBUG_SYNC="now WAIT_FOR con1_go"; +BEGIN; +SELECT * FROM t1; +f1 f2 +SET DEBUG_SYNC="now SIGNAL alter_signal"; +connection default; +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +connection con1; +rollback; +connection default; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) GENERATED ALWAYS AS (`f1`) VIRTUAL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; +SET DEBUG_DBUG="+d,create_index_fail"; +SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; +ALTER TABLE t1 ADD INDEX(f2); +connection con1; +SET DEBUG_SYNC="now WAIT_FOR con1_go"; +BEGIN; +INSERT INTO t1(f1) VALUES(1); +SET DEBUG_SYNC="now SIGNAL alter_signal"; +connection default; +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +connection con1; +rollback; +connection default; +disconnect con1; +DROP TABLE t1; +CREATE TABLE t1(f1 CHAR(100), f2 CHAR(100) as (f1) VIRTUAL)ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN f3 CHAR(100) AS (f2) VIRTUAL, ADD INDEX(f3(10), f1, f3(12)); +ERROR 42S21: Duplicate column name 'f3' +DROP TABLE t1; +SET DEBUG_SYNC=RESET; diff --git a/mysql-test/suite/gcol/t/virtual_index_drop.test b/mysql-test/suite/gcol/t/virtual_index_drop.test new file mode 100644 index 00000000000..016832b9e6d --- /dev/null +++ b/mysql-test/suite/gcol/t/virtual_index_drop.test @@ -0,0 +1,71 @@ +--source include/have_innodb.inc +--source include/have_debug.inc + +--echo # +--echo # MDEV-24971 InnoDB access freed virtual column +--echo # after rollback of secondary index +--echo # + +# Exclusive lock must not defer the index removal + +CREATE TABLE t1(f1 INT, f2 INT AS (f1 + 2) VIRTUAL)ENGINE=InnoDB; +INSERT INTO t1(f1) VALUES(1), (1); +--error ER_DUP_ENTRY +ALTER TABLE t1 ADD UNIQUE INDEX(f2), ALGORITHM=INPLACE, LOCK=EXCLUSIVE; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# If Shared lock and table doesn't have any other open handle +# then InnoDB must not defer the index removal + +CREATE TABLE t1(f1 INT, f2 INT AS (f1 + 2) VIRTUAL)ENGINE=InnoDB; +INSERT INTO t1(f1) VALUES(1), (1); +--error ER_DUP_ENTRY +ALTER TABLE t1 ADD UNIQUE INDEX(f2), ALGORITHM=INPLACE, LOCK=SHARED; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# InnoDB should store the newly dropped virtual column into +# new_vcol_info in index when rollback of alter happens + +CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; +SET DEBUG_DBUG="+d,create_index_fail"; +SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; +SEND ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3); +connect(con1,localhost,root,,,); +SET DEBUG_SYNC="now WAIT_FOR con1_go"; +BEGIN; +SELECT * FROM t1; +SET DEBUG_SYNC="now SIGNAL alter_signal"; +connection default; +--error ER_DUP_ENTRY +reap; +connection con1; +rollback; +connection default; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB; +SET DEBUG_DBUG="+d,create_index_fail"; +SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; +send ALTER TABLE t1 ADD INDEX(f2); +connection con1; +SET DEBUG_SYNC="now WAIT_FOR con1_go"; +BEGIN; +INSERT INTO t1(f1) VALUES(1); +SET DEBUG_SYNC="now SIGNAL alter_signal"; +connection default; +--error ER_DUP_ENTRY +reap; +connection con1; +rollback; +connection default; +disconnect con1; +DROP TABLE t1; + +CREATE TABLE t1(f1 CHAR(100), f2 CHAR(100) as (f1) VIRTUAL)ENGINE=InnoDB; +--error ER_DUP_FIELDNAME +ALTER TABLE t1 ADD COLUMN f3 CHAR(100) AS (f2) VIRTUAL, ADD INDEX(f3(10), f1, f3(12)); +DROP TABLE t1; +SET DEBUG_SYNC=RESET; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 6f546dfbd94..d6330cb5906 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -297,7 +297,7 @@ dict_table_try_drop_aborted( && !UT_LIST_GET_FIRST(table->locks)) { /* Silence a debug assertion in row_merge_drop_indexes(). */ ut_d(table->acquire()); - row_merge_drop_indexes(trx, table, TRUE); + row_merge_drop_indexes(trx, table, true); ut_d(table->release()); ut_ad(table->get_ref_count() == ref_count); trx_commit_for_mysql(trx); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index efefa40e69f..1667e1a0b20 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -911,7 +911,7 @@ dict_mem_fill_vcol_from_v_indexes( Later virtual column set will be refreshed during loading of table. */ if (!dict_index_has_virtual(index) - || index->has_new_v_col) { + || index->has_new_v_col()) { continue; } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index ccc3fe3b921..1f6dbe1eda9 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -248,13 +248,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx @return whether the table will be rebuilt */ bool need_rebuild () const { return(old_table != new_table); } - /** Clear uncommmitted added indexes after a failed operation. */ - void clear_added_indexes() - { - for (ulint i= 0; i < num_to_add_index; i++) - add_index[i]->detach_columns(true); - } - /** Share context between partitions. @param[in] ctx context from another partition of the table */ void set_shared_data(const inplace_alter_handler_ctx& ctx) @@ -272,6 +265,45 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx } } + /** @return whether the given column is being added */ + bool is_new_vcol(const dict_v_col_t &v_col) const + { + for (ulint i= 0; i < num_to_add_vcol; i++) + if (&add_vcol[i] == &v_col) + return true; + return false; + } + + /** During rollback, make newly added indexes point to + newly added virtual columns. */ + void clean_new_vcol_index() + { + ut_ad(old_table == new_table); + const dict_index_t *index= dict_table_get_first_index(old_table); + while ((index= dict_table_get_next_index(index)) != NULL) + { + if (!index->has_virtual() || index->is_committed()) + continue; + ulint n_drop_new_vcol= index->get_new_n_vcol(); + for (ulint i= 0; n_drop_new_vcol && i < index->n_fields; i++) + { + dict_col_t *col= index->fields[i].col; + /* Skip the non-virtual and old virtual columns */ + if (!col->is_virtual()) + continue; + dict_v_col_t *vcol= reinterpret_cast(col); + if (!is_new_vcol(*vcol)) + continue; + + dict_v_col_t *drop_vcol= index->new_vcol_info-> + add_drop_v_col(index->heap, vcol, n_drop_new_vcol); + /* Re-assign the index field with newly stored virtual column */ + index->fields[i].col= reinterpret_cast(drop_vcol); + n_drop_new_vcol--; + } + } + } + private: // Disable copying ha_innobase_inplace_ctx(const ha_innobase_inplace_ctx&); @@ -2722,7 +2754,7 @@ online_retry_drop_indexes_low( ut_ad(table->get_ref_count() >= 1); if (table->drop_aborted) { - row_merge_drop_indexes(trx, table, TRUE); + row_merge_drop_indexes(trx, table, true); } } @@ -5146,7 +5178,7 @@ error_handled: online_retry_drop_indexes_with_trx(user_table, ctx->trx); } else { ut_ad(!ctx->need_rebuild()); - row_merge_drop_indexes(ctx->trx, user_table, TRUE); + row_merge_drop_indexes(ctx->trx, user_table, true); trx_commit_for_mysql(ctx->trx); } @@ -6388,7 +6420,6 @@ oom: that we hold at most a shared lock on the table. */ m_prebuilt->trx->error_info = NULL; ctx->trx->error_state = DB_SUCCESS; - ctx->clear_added_indexes(); DBUG_RETURN(true); } @@ -6483,17 +6514,18 @@ temparary index prefix @param table the TABLE @param locked TRUE=table locked, FALSE=may need to do a lazy drop @param trx the transaction -*/ -static MY_ATTRIBUTE((nonnull)) +@param alter_trx transaction which takes S-lock on the table + while creating the index */ +static void innobase_rollback_sec_index( -/*========================*/ - dict_table_t* user_table, - const TABLE* table, - ibool locked, - trx_t* trx) + dict_table_t* user_table, + const TABLE* table, + bool locked, + trx_t* trx, + const trx_t* alter_trx=NULL) { - row_merge_drop_indexes(trx, user_table, locked); + row_merge_drop_indexes(trx, user_table, locked, alter_trx); /* Free the table->fts only if there is no FTS_DOC_ID in the table */ @@ -6587,7 +6619,12 @@ rollback_inplace_alter_table( DBUG_ASSERT(ctx->new_table == prebuilt->table); innobase_rollback_sec_index( - prebuilt->table, table, FALSE, ctx->trx); + prebuilt->table, table, + (ha_alter_info->alter_info->requested_lock + == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE), + ctx->trx, prebuilt->trx); + + ctx->clean_new_vcol_index(); } trx_commit_for_mysql(ctx->trx); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index a4defe4d92a..7ca1ad9ecd3 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -671,6 +671,35 @@ struct dict_v_col_t{ }; +/** Data structure for newly added virtual column in a index. +It is used only during rollback_inplace_alter_table() of +addition of index depending on newly added virtual columns +and uses index heap. Should be freed when index is being +removed from cache. */ +struct dict_add_v_col_info +{ + ulint n_v_col; + dict_v_col_t *v_col; + + /** Add the newly added virtual column while rollbacking + the index which contains new virtual columns + @param col virtual column to be duplicated + @param offset offset where to duplicate virtual column */ + dict_v_col_t* add_drop_v_col(mem_heap_t *heap, dict_v_col_t *col, + ulint offset) + { + ut_ad(n_v_col); + ut_ad(offset < n_v_col); + if (!v_col) + v_col= static_cast + (mem_heap_alloc(heap, n_v_col * sizeof *v_col)); + new (&v_col[offset]) dict_v_col_t(); + v_col[offset].m_col= col->m_col; + v_col[offset].v_pos= col->v_pos; + return &v_col[offset]; + } +}; + /** Data structure for newly added virtual column in a table */ struct dict_add_v_col_t{ /** number of new virtual column */ @@ -892,9 +921,13 @@ struct dict_index_t{ dict_field_t* fields; /*!< array of field descriptions */ st_mysql_ftparser* parser; /*!< fulltext parser plugin */ - bool has_new_v_col; - /*!< whether it has a newly added virtual - column in ALTER */ + + /** It just indicates whether newly added virtual column + during alter. It stores column in case of alter failure. + It should use heap from dict_index_t. It should be freed + while removing the index from table. */ + dict_add_v_col_info* new_vcol_info; + bool index_fts_syncing;/*!< Whether the fts index is still syncing in the background; FIXME: remove this and use MDL */ @@ -1028,9 +1061,8 @@ struct dict_index_t{ /** @return whether the index is corrupted */ inline bool is_corrupted() const; - /** Detach the virtual columns from the index that is to be removed. - @param whether to reset fields[].col */ - void detach_columns(bool clear= false) + /** Detach the virtual columns from the index that is to be removed. */ + void detach_columns() { if (!has_virtual()) return; @@ -1040,14 +1072,36 @@ struct dict_index_t{ if (!col || !col->is_virtual()) continue; col->detach(*this); - if (clear) - fields[i].col= NULL; } } /** @return whether this is the change buffer */ bool is_ibuf() const { return UNIV_UNLIKELY(type & DICT_IBUF); } + /** Assign the number of new column to be added as a part + of the index + @param n_vcol number of virtual columns to be added */ + void assign_new_v_col(ulint n_vcol) + { + new_vcol_info= static_cast( + mem_heap_zalloc(heap, sizeof *new_vcol_info)); + new_vcol_info->n_v_col= n_vcol; + } + + /* @return whether index has new virtual column */ + bool has_new_v_col() const + { + return new_vcol_info != NULL; + } + + /* @return number of newly added virtual column */ + ulint get_new_n_vcol() const + { + if (new_vcol_info) + return new_vcol_info->n_v_col; + return 0; + } + #ifdef BTR_CUR_HASH_ADAPT /** @return a clone of this */ dict_index_t* clone() const; @@ -1870,6 +1924,17 @@ public: /** mysql_row_templ_t for base columns used for compute the virtual columns */ dict_vcol_templ_t* vc_templ; + + /* @return whether the table has any other transcation lock + other than the given transaction */ + bool has_lock_other_than(const trx_t *trx) const + { + for (lock_t *lock= UT_LIST_GET_FIRST(locks); lock; + lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) + if (lock->trx != trx) + return true; + return false; + } }; inline bool table_name_t::is_temporary() const diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h index 0d48fbd2e8a..dfd1d9fb9fd 100644 --- a/storage/innobase/include/row0merge.h +++ b/storage/innobase/include/row0merge.h @@ -167,18 +167,20 @@ row_merge_drop_indexes_dict( table_id_t table_id)/*!< in: table identifier */ MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** -Drop those indexes which were created before an error occurred. +/** Drop indexes that were created before an error occurred. The data dictionary must have been locked exclusively by the caller, -because the transaction will not be committed. */ +because the transaction will not be committed. +@param trx dictionary transaction +@param table table containing the indexes +@param locked True if table is locked, + false - may need to do lazy drop +@param alter_trx Alter table transaction */ void row_merge_drop_indexes( -/*===================*/ - trx_t* trx, /*!< in/out: transaction */ - dict_table_t* table, /*!< in/out: table containing the indexes */ - ibool locked) /*!< in: TRUE=table locked, - FALSE=may need to do a lazy drop */ - MY_ATTRIBUTE((nonnull)); + trx_t* trx, + dict_table_t* table, + bool locked, + const trx_t* alter_trx=NULL); /*********************************************************************//** Drop all partially created indexes during crash recovery. */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 835d74043fd..e3b3f2c2762 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -3696,17 +3696,20 @@ row_merge_drop_indexes_dict( trx->op_info = ""; } -/*********************************************************************//** -Drop indexes that were created before an error occurred. +/** Drop indexes that were created before an error occurred. The data dictionary must have been locked exclusively by the caller, -because the transaction will not be committed. */ +because the transaction will not be committed. +@param trx dictionary transaction +@param table table containing the indexes +@param locked True if table is locked, + false - may need to do lazy drop +@param alter_trx Alter table transaction */ void row_merge_drop_indexes( -/*===================*/ - trx_t* trx, /*!< in/out: dictionary transaction */ - dict_table_t* table, /*!< in/out: table containing the indexes */ - ibool locked) /*!< in: TRUE=table locked, - FALSE=may need to do a lazy drop */ + trx_t* trx, + dict_table_t* table, + bool locked, + const trx_t* alter_trx) { dict_index_t* index; dict_index_t* next_index; @@ -3732,7 +3735,7 @@ row_merge_drop_indexes( A concurrent purge will be prevented by dict_operation_lock. */ if (!locked && (table->get_ref_count() > 1 - || UT_LIST_GET_FIRST(table->locks))) { + || table->has_lock_other_than(alter_trx))) { /* We will have to drop the indexes later, when the table is guaranteed to be no longer in use. Mark the indexes as incomplete and corrupted, so that other @@ -4363,7 +4366,7 @@ row_merge_create_index( dberr_t err; ulint n_fields = index_def->n_fields; ulint i; - bool has_new_v_col = false; + ulint n_add_vcol = 0; DBUG_ENTER("row_merge_create_index"); @@ -4391,7 +4394,7 @@ row_merge_create_index( ut_ad(ifield->col_no >= table->n_v_def); name = add_v->v_col_name[ ifield->col_no - table->n_v_def]; - has_new_v_col = true; + n_add_vcol++; } else { name = dict_table_get_v_col_name( table, ifield->col_no); @@ -4410,7 +4413,9 @@ row_merge_create_index( if (err == DB_SUCCESS) { ut_ad(index != index_template); index->parser = index_def->parser; - index->has_new_v_col = has_new_v_col; + if (n_add_vcol) { + index->assign_new_v_col(n_add_vcol); + } /* Note the id of the transaction that created this index, we use it to restrict readers from accessing this index, to ensure read consistency. */ diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index e79784a5a5f..024625e9e0a 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -729,7 +729,7 @@ row_purge_skip_uncommitted_virtual_index( not support LOCK=NONE when adding an index on newly added virtual column.*/ while (index != NULL && dict_index_has_virtual(index) - && !index->is_committed() && index->has_new_v_col) { + && !index->is_committed() && index->has_new_v_col()) { index = dict_table_get_next_index(index); } } From e95cdc451a969ab8186eabe76be19f578182e946 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 12 Apr 2021 04:11:28 +0200 Subject: [PATCH 28/35] MDEV-21484: galera_sst_mariabackup_encrypt_with_key test failed This commit removes the mtr test galera_sst_mariabackup_encrypt_with_key from the list of disabled tests because the problem with it has already been fixed. --- mysql-test/suite/galera/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 6285da7b11c..d9483864844 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -20,7 +20,6 @@ galera_mdl_race : MDEV-21524: galera.galera_mdl_race MTR failed: query 'reap' su galera_parallel_simple : MDEV-20318 galera.galera_parallel_simple fails galera_partition : MDEV-21806: galera.galera_partition MTR failed: failed to recover from DONOR state galera_shutdown_nonprim : MDEV-21493 galera.galera_shutdown_nonprim -galera_sst_mariabackup_encrypt_with_key : MDEV-21484 galera_sst_mariabackup_encrypt_with_key galera_var_node_address : MDEV-20485 Galera test failure galera_wan : MDEV-17259 Test failure on galera.galera_wan partition : MDEV-19958 Galera test failure on galera.partition From f8bf2a0170b385bbba8f9f8dc97841f58229d39a Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Mon, 12 Apr 2021 19:28:10 +0700 Subject: [PATCH 29/35] MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning in case it is executed in PS (prepared statement) mode The EXPLAIN EXTENDED statement run as a prepared statement can produce extra warning comparing with a case when EXPLAIN EXTENDED statement is run as a regular statement. For example, the following test case CREATE TABLE t1 (c int); CREATE TABLE t2 (d int); EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1; produces the extra warning "Field or reference 'c' of SELECT #2 was resolved in SELECT #1" in case the above mentioned "EXPLAIN EXTENDED" statement is executed in PS mode, that is by submitting the following statements: PREPARE stmt FROM "EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1"; EXECUTE stmt; The reason of the extra warning emittion is in a way items are handled (being fixed) during execution of the JOIN::prepare() method. The method Item_field::fix_fields() calls the find_field_in_tables() function in case a field hasn't been associated yet with the item. Implementation of the find_field_in_tables() function first checks whether a table containing the required field was already opened and cached. It is done by checking the data member item->cached_table. This data member is set on handling the PRERARE FROM statement and checked on executing the EXECUTE statement. If the data member item->cached_table is set the find_field_in_tables() function invoked and the mark_select_range_as_dependent() function called if the field is an outer referencee. The mark_select_range_as_dependent() function calls the mark_as_dependent() function that finally invokes the push_warning_printf() function that produces extra warning. To fix the issue, calling of push_warning_printf() is elimited in case it was run indirectly in result of hanlding already opened table from the Item_field::fix_fields() method. --- mysql-test/r/ps.result | 37 +++++++++++++++++++++++++++++++++++++ mysql-test/t/ps.test | 20 ++++++++++++++++++++ sql/item.cc | 30 ++++++++++++++++++------------ sql/item.h | 3 ++- sql/item_subselect.h | 3 ++- sql/sql_base.cc | 2 +- 6 files changed, 80 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 17284a3cad8..4ee72f10785 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -5419,5 +5419,42 @@ id select_type table type possible_keys key key_len ref rows Extra DEALLOCATE PREPARE stmt; DROP TABLE t1; # +# MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning +# in case it is executed in PS (prepared statement) mode +# +CREATE TABLE t1 (c int); +CREATE TABLE t2 (d int); +# EXPLAIN EXTENDED in regular way (not PS mode) +EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 +Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1` +SHOW WARNINGS; +Level Code Message +Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 +Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1` +# Now run the same EXPLAIN EXTENDED in PS mode. Number of warnings +# and their content must be the same as in case running the statement +# in regular way +PREPARE stmt FROM "EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1"; +Warnings: +Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 +EXECUTE stmt; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 +Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1` +SHOW WARNINGS; +Level Code Message +Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 +Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1` +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; +# # End of 10.2 tests # diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index a267c8b0e42..5b86f82a9cb 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -4926,6 +4926,26 @@ EXECUTE stmt; DEALLOCATE PREPARE stmt; DROP TABLE t1; +--echo # +--echo # MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning +--echo # in case it is executed in PS (prepared statement) mode +--echo # +CREATE TABLE t1 (c int); +CREATE TABLE t2 (d int); + +--echo # EXPLAIN EXTENDED in regular way (not PS mode) +EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1; +SHOW WARNINGS; + +--echo # Now run the same EXPLAIN EXTENDED in PS mode. Number of warnings +--echo # and their content must be the same as in case running the statement +--echo # in regular way +PREPARE stmt FROM "EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1"; +EXECUTE stmt; +SHOW WARNINGS; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 45f40874ddb..55d135c660e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4668,11 +4668,14 @@ bool Item_ref_null_helper::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) @param resolved_item item which was resolved in outer SELECT(for warning) @param mark_item item which should be marked (can be differ in case of substitution) + @param suppress_warning_output flag specifying whether to suppress output of + a warning message */ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, Item_ident *resolved_item, - Item_ident *mark_item) + Item_ident *mark_item, + bool suppress_warning_output) { DBUG_ENTER("mark_as_dependent"); @@ -4685,7 +4688,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, if (current->mark_as_dependent(thd, last, /** resolved_item psergey-thu **/ mark_item)) DBUG_RETURN(TRUE); - if (thd->lex->describe & DESCRIBE_EXTENDED) + if ((thd->lex->describe & DESCRIBE_EXTENDED) && !suppress_warning_output) { const char *db_name= (resolved_item->db_name ? resolved_item->db_name : ""); @@ -4714,6 +4717,8 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, @param found_item Item which was found during resolving (if resolved identifier belongs to VIEW) @param resolved_item Identifier which was resolved + @param suppress_warning_output flag specifying whether to suppress output of + a warning message @note We have to mark all items between current_sel (including) and @@ -4727,7 +4732,8 @@ void mark_select_range_as_dependent(THD *thd, SELECT_LEX *last_select, SELECT_LEX *current_sel, Field *found_field, Item *found_item, - Item_ident *resolved_item) + Item_ident *resolved_item, + bool suppress_warning_output) { /* Go from current SELECT to SELECT where field was resolved (it @@ -4762,7 +4768,7 @@ void mark_select_range_as_dependent(THD *thd, found_field->table->map; prev_subselect_item->const_item_cache= 0; mark_as_dependent(thd, last_select, current_sel, resolved_item, - dependent); + dependent, suppress_warning_output); } } @@ -5228,7 +5234,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) context->select_lex, this, ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? - (Item_ident*) (*reference) : 0)); + (Item_ident*) (*reference) : 0), false); return 0; } } @@ -5240,7 +5246,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) context->select_lex, this, ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : - 0)); + 0), false); if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level >= select->nest_level) { @@ -5354,7 +5360,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) set_max_sum_func_level(thd, select); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, rf, - rf); + rf, false); return 0; } @@ -5367,7 +5373,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) set_max_sum_func_level(thd, select); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, - this, (Item_ident*)*reference); + this, (Item_ident*)*reference, false); if (last_checked_context->select_lex->having_fix_field) { Item_ref *rf; @@ -7401,7 +7407,7 @@ public: if (tbl->table == item->field->table) { if (sel != current_select) - mark_as_dependent(thd, sel, current_select, item, item); + mark_as_dependent(thd, sel, current_select, item, item, false); return; } } @@ -7596,7 +7602,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ((refer_type == REF_ITEM || refer_type == FIELD_ITEM) ? (Item_ident*) (*reference) : - 0)); + 0), false); /* view reference found, we substituted it instead of this Item, so can quit @@ -7646,7 +7652,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) goto error; thd->change_item_tree(reference, fld); mark_as_dependent(thd, last_checked_context->select_lex, - current_sel, fld, fld); + current_sel, fld, fld, false); /* A reference is resolved to a nest level that's outer or the same as the nest level of the enclosing set function : adjust the value of @@ -7669,7 +7675,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) /* Should be checked in resolve_ref_in_select_and_group(). */ DBUG_ASSERT(*ref && (*ref)->fixed); mark_as_dependent(thd, last_checked_context->select_lex, - context->select_lex, this, this); + context->select_lex, this, this, false); /* A reference is resolved to a nest level that's outer or the same as the nest level of the enclosing set function : adjust the value of diff --git a/sql/item.h b/sql/item.h index cb1e8519b27..b13336939f9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -6088,7 +6088,8 @@ void mark_select_range_as_dependent(THD *thd, st_select_lex *last_select, st_select_lex *current_sel, Field *found_field, Item *found_item, - Item_ident *resolved_item); + Item_ident *resolved_item, + bool suppress_warning_output); extern Cached_item *new_Cached_item(THD *thd, Item *item, bool pass_through_ref); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 130f90839e3..7b2078939f1 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -283,7 +283,8 @@ public: friend bool Item_ref::fix_fields(THD *, Item **); friend void mark_select_range_as_dependent(THD*, st_select_lex*, st_select_lex*, - Field*, Item*, Item_ident*); + Field*, Item*, Item_ident*, + bool); friend bool convert_join_subqueries_to_semijoins(JOIN *join); }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b8d18abb50c..f10846acdd7 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6046,7 +6046,7 @@ find_field_in_tables(THD *thd, Item_ident *item, if (!all_merged && current_sel != last_select) { mark_select_range_as_dependent(thd, last_select, current_sel, - found, *ref, item); + found, *ref, item, true); } } return found; From 68e0defc5be41e42f5f9d050a436a5f88277a586 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 12 Apr 2021 15:46:23 +0200 Subject: [PATCH 30/35] MDEV-25182 Complex query in Store procedure corrupts results At the second execution of the PS 1. mark_as_dependent() is called with the same parameters as at the first execution (select#4 and select#3) 2. as outer_select (select#3) has been already merged at the first execution of PS it cannot be reached using the outer_select() function anymore (and so can not stop iteration). 3. as a result all selects towards the top level select including the select for 'ca' are marked as uncacheable. 4. Marked uncacheable it executed incorrectly triggering filling its temporary table several times and using freed memory at the end. To avoid the problem we use name resolution context to go "up". NOTE: problem also exists in 10.2 but has no visible effect on execution. That is why the problem is fixed in 10.2. The patch also add debug logging of important procedures and better specify parameters types of st_select_lex::mark_as_dependent. --- mysql-test/r/derived_opt.result | 27 +++++++++++++++++++++++++++ mysql-test/t/derived_opt.test | 33 +++++++++++++++++++++++++++++++++ sql/item.cc | 3 +++ sql/sql_lex.cc | 10 +++++++--- sql/sql_lex.h | 3 ++- sql/sql_select.cc | 8 +++++--- 6 files changed, 77 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/derived_opt.result b/mysql-test/r/derived_opt.result index 0e8b49d5714..069b0aa65c9 100644 --- a/mysql-test/r/derived_opt.result +++ b/mysql-test/r/derived_opt.result @@ -537,4 +537,31 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort set join_cache_level=default; DROP TABLE t1,t2; +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch="derived_merge=on"; +CREATE TABLE t1 (id int, d2 datetime, id1 int) ; +insert into t1 values (1,'2020-01-01 10:10:10',1),(2,'2020-01-01 10:10:10',2),(3,'2020-01-01 10:10:10',3); +CREATE TABLE t2 (id int, d1 datetime, id1 int) ; +insert into t2 values (1,'2020-01-01 10:10:10',1),(2,'2020-01-01 10:10:10',2),(3,'2020-01-01 10:10:10',2); +prepare stmt from " +SELECT * from + (SELECT min(d2) AS d2, min(d1) AS d1 FROM + (SELECT t1.d2 AS d2, (SELECT t2.d1 + FROM t2 WHERE t1.id1 = t2.id1 + ORDER BY t2.id DESC LIMIT 1) AS d1 + FROM t1 + ) dt2 + ) ca + ORDER BY ca.d2;"; +execute stmt; +d2 d1 +2020-01-01 10:10:10 2020-01-01 10:10:10 +execute stmt; +d2 d1 +2020-01-01 10:10:10 2020-01-01 10:10:10 +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1, t2; +# +# End of 10.3 tests +# set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/t/derived_opt.test b/mysql-test/t/derived_opt.test index aab95f69f26..305cac120a0 100644 --- a/mysql-test/t/derived_opt.test +++ b/mysql-test/t/derived_opt.test @@ -401,5 +401,38 @@ set join_cache_level=default; DROP TABLE t1,t2; +# +# MDEV-25182: Complex query in Store procedure corrupts results +# +set @save_optimizer_switch= @@optimizer_switch; +set optimizer_switch="derived_merge=on"; + +CREATE TABLE t1 (id int, d2 datetime, id1 int) ; +insert into t1 values (1,'2020-01-01 10:10:10',1),(2,'2020-01-01 10:10:10',2),(3,'2020-01-01 10:10:10',3); + +CREATE TABLE t2 (id int, d1 datetime, id1 int) ; +insert into t2 values (1,'2020-01-01 10:10:10',1),(2,'2020-01-01 10:10:10',2),(3,'2020-01-01 10:10:10',2); + +prepare stmt from " +SELECT * from + (SELECT min(d2) AS d2, min(d1) AS d1 FROM + (SELECT t1.d2 AS d2, (SELECT t2.d1 + FROM t2 WHERE t1.id1 = t2.id1 + ORDER BY t2.id DESC LIMIT 1) AS d1 + FROM t1 + ) dt2 + ) ca + ORDER BY ca.d2;"; + +execute stmt; +execute stmt; + +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1, t2; + +--echo # +--echo # End of 10.3 tests +--echo # + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; diff --git a/sql/item.cc b/sql/item.cc index 55d135c660e..42272fe0148 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4678,6 +4678,9 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, bool suppress_warning_output) { DBUG_ENTER("mark_as_dependent"); + DBUG_PRINT("info", ("current select: %d (%p) last: %d (%p)", + current->select_number, current, + (last ? last->select_number : 0), last)); /* store pointer on SELECT_LEX from which item is dependent */ if (mark_item && mark_item->can_be_depended) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5059e4f656e..bfe773b2c00 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2470,7 +2470,7 @@ void st_select_lex_unit::exclude_tree() */ bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, - Item *dependency) + Item_ident *dependency) { DBUG_ASSERT(this != last); @@ -2478,10 +2478,14 @@ bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, /* Mark all selects from resolved to 1 before select where was found table as depended (of select where was found table) + + We move by name resolution context, bacause during merge can some select + be excleded from SELECT tree */ - SELECT_LEX *s= this; + Name_resolution_context *c= &this->context; do { + SELECT_LEX *s= c->select_lex; if (!(s->uncacheable & UNCACHEABLE_DEPENDENT_GENERATED)) { // Select is dependent of outer select @@ -2503,7 +2507,7 @@ bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, if (subquery_expr && subquery_expr->mark_as_dependent(thd, last, dependency)) return TRUE; - } while ((s= s->outer_select()) != last && s != 0); + } while ((c= c->outer_context) != NULL && (c->select_lex != last)); is_correlated= TRUE; this->master_unit()->item->is_correlated= TRUE; return FALSE; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f733f783d0e..31751a16471 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1004,7 +1004,8 @@ public: } inline bool is_subquery_function() { return master_unit()->item != 0; } - bool mark_as_dependent(THD *thd, st_select_lex *last, Item *dependency); + bool mark_as_dependent(THD *thd, st_select_lex *last, + Item_ident *dependency); void set_braces(bool value) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7bfbf719017..90c071803a1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12097,10 +12097,12 @@ ha_rows JOIN_TAB::get_examined_rows() bool JOIN_TAB::preread_init() { TABLE_LIST *derived= table->pos_in_table_list; + DBUG_ENTER("JOIN_TAB::preread_init"); + if (!derived || !derived->is_materialized_derived()) { preread_init_done= TRUE; - return FALSE; + DBUG_RETURN(FALSE); } /* Materialize derived table/view. */ @@ -12108,7 +12110,7 @@ bool JOIN_TAB::preread_init() derived->is_recursive_with_table()) && mysql_handle_single_derived(join->thd->lex, derived, DT_CREATE | DT_FILL)) - return TRUE; + DBUG_RETURN(TRUE); preread_init_done= TRUE; if (select && select->quick) @@ -12125,7 +12127,7 @@ bool JOIN_TAB::preread_init() if (table->fulltext_searched) init_ftfuncs(join->thd, join->select_lex, MY_TEST(join->order)); - return FALSE; + DBUG_RETURN(FALSE); } From f776fa96b4e04644155087a2c3919be13c1000a6 Mon Sep 17 00:00:00 2001 From: Dmitriy Karpovskiy Date: Wed, 3 Feb 2021 12:04:06 +0300 Subject: [PATCH 31/35] MDEV-24135: Print warnings in XML, save test retries in XML, save the combinations in XML, replace the special symbols in the XML comment --- mysql-test/lib/mtr_report.pm | 30 +++++++++++++++++++----------- mysql-test/mysql-test-run.pl | 10 +++++++--- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 98ed77eea0f..8142b0a5cbb 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -497,23 +497,21 @@ sub mtr_report_stats ($$$$) { $test_time = sprintf("%.3f", $test->{timer} / 1000); $test->{'name'} =~ s/$current_suite\.//; - my $test_result; - - # if a test case has to be retried it should have the result MTR_RES_FAILED in jUnit XML - if ($test->{'retries'} > 0) { - $test_result = "MTR_RES_FAILED"; + my $combinations; + if (defined($test->{combinations})){ + $combinations = join ',', sort @{$test->{combinations}}; } else { - $test_result = $test->{'result'}; + $combinations = ""; } - $xml_report .= qq(\t\t{'comment'}; - $comment =~ s/[\"]//g; + my $comment= replace_special_symbols($test->{'comment'}); - # if a test case has to be retried it should have the result MTR_RES_FAILED in jUnit XML - if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'} > 0) { + if ($test->{'result'} eq "MTR_RES_FAILED") { my $logcontents = $test->{'logfile-failed'} || $test->{'logfile'}; + $logcontents= $logcontents.$test->{'warnings'}."\n"; # remove any double ] that would end the cdata $logcontents =~ s/]]/\x{fffd}/g; # replace wide characters that aren't allowed in XML 1.0 @@ -576,6 +574,16 @@ sub mtr_print_line () { print '-' x 74 . "\n"; } +sub replace_special_symbols($) { + my $text= shift; + $text =~ s/&/&/g; + $text =~ s/'/'/g; + $text =~ s/"/"/g; + $text =~ s//>/g; + return $text; +} + sub mtr_print_thick_line { my $char= shift || '='; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index fd25c28dc06..5e46cfe8eff 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -888,9 +888,13 @@ sub run_test_server ($$$) { rename $log_file_name, $log_file_name.".failed"; } - delete($result->{result}); - $result->{retries}= $retries+1; - $result->write_test($sock, 'TESTCASE'); + { + local @$result{'retries', 'result'}; + delete $result->{result}; + $result->{retries}= $retries+1; + $result->write_test($sock, 'TESTCASE'); + } + push(@$completed, $result); next; } } From e262eb165c197083df9f4986ab54c5b2dcbd6290 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 13 Apr 2021 10:09:16 +0530 Subject: [PATCH 32/35] MDEV-24971 InnoDB access freed virtual column after rollback of secondary index - Fixing post-fix failure. In clean_new_vcol_index(), InnoDB has the wrong offset to store the virtual column --- storage/innobase/handler/handler0alter.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 1f6dbe1eda9..3ac4f4fe4c1 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -296,10 +296,9 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx continue; dict_v_col_t *drop_vcol= index->new_vcol_info-> - add_drop_v_col(index->heap, vcol, n_drop_new_vcol); + add_drop_v_col(index->heap, vcol, --n_drop_new_vcol); /* Re-assign the index field with newly stored virtual column */ index->fields[i].col= reinterpret_cast(drop_vcol); - n_drop_new_vcol--; } } } From b8c8692fd93b68df8f70db5ffab82ed0d67008b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 13 Apr 2021 10:28:13 +0300 Subject: [PATCH 33/35] MDEV-24620 ASAN heap-buffer-overflow in btr_pcur_restore_position() Between btr_pcur_store_position() and btr_pcur_restore_position() it is possible that purge empties a table and enlarges index->n_core_fields and index->n_core_null_bytes. Therefore, we must cache index->n_core_fields in btr_pcur_t::old_n_core_fields so that btr_pcur_t::old_rec can be parsed correctly. Unfortunately, this is a huge change, because we will replace "bool leaf" parameters with "ulint n_core" (passing index->n_core_fields, or 0 for non-leaf pages). For special cases where we know that index->is_instant() cannot hold, we may also pass index->n_fields. --- .../suite/innodb/r/instant_alter_debug.result | 28 +++++++ .../suite/innodb/t/instant_alter_debug.test | 38 ++++++++++ storage/innobase/btr/btr0btr.cc | 51 ++++++++----- storage/innobase/btr/btr0bulk.cc | 28 ++++--- storage/innobase/btr/btr0cur.cc | 43 ++++++----- storage/innobase/btr/btr0defragment.cc | 9 ++- storage/innobase/btr/btr0pcur.cc | 51 +++++++++++-- storage/innobase/btr/btr0sea.cc | 31 +++++--- storage/innobase/dict/dict0dict.cc | 51 ++----------- storage/innobase/dict/dict0mem.cc | 5 +- storage/innobase/dict/dict0stats.cc | 32 ++++---- storage/innobase/fts/fts0fts.cc | 11 ++- storage/innobase/gis/gis0rtree.cc | 68 +++++++++-------- storage/innobase/gis/gis0sea.cc | 67 +++++++++-------- storage/innobase/ibuf/ibuf0ibuf.cc | 9 ++- storage/innobase/include/btr0pcur.h | 6 +- storage/innobase/include/dict0dict.h | 17 +---- storage/innobase/include/dict0mem.h | 11 ++- storage/innobase/include/gis0rtree.ic | 5 +- storage/innobase/include/page0cur.ic | 5 +- storage/innobase/include/rem0rec.h | 12 +-- storage/innobase/lock/lock0lock.cc | 15 ++-- storage/innobase/page/page0cur.cc | 61 ++++++++------- storage/innobase/page/page0page.cc | 33 +++++---- storage/innobase/page/page0zip.cc | 32 ++++---- storage/innobase/rem/rem0rec.cc | 74 +++++++++++-------- storage/innobase/row/row0import.cc | 6 +- storage/innobase/row/row0ins.cc | 25 ++++--- storage/innobase/row/row0log.cc | 13 ++-- storage/innobase/row/row0merge.cc | 6 +- storage/innobase/row/row0mysql.cc | 17 +++-- storage/innobase/row/row0purge.cc | 11 +-- storage/innobase/row/row0row.cc | 10 ++- storage/innobase/row/row0sel.cc | 57 ++++++++------ storage/innobase/row/row0uins.cc | 5 +- storage/innobase/row/row0umod.cc | 13 ++-- storage/innobase/row/row0undo.cc | 5 +- storage/innobase/row/row0upd.cc | 22 +++--- storage/innobase/row/row0vers.cc | 40 ++++++---- storage/innobase/trx/trx0i_s.cc | 3 +- storage/innobase/trx/trx0rec.cc | 5 +- storage/innobase/ut/ut0ut.cc | 4 +- 42 files changed, 614 insertions(+), 421 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 3b85be1ef1c..a189479d772 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -317,5 +317,33 @@ SELECT * FROM t1 WHERE c<>1 ORDER BY c DESC; c d DROP TABLE t1; SET GLOBAL innodb_limit_optimistic_insert_debug = @saved_limit; +# +# MDEV-24620 ASAN heap-buffer-overflow in btr_pcur_restore_position() +# +CREATE TABLE t1 (a VARCHAR(1) PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +connect stop_purge,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +ALTER TABLE t1 ADD c INT; +BEGIN; +DELETE FROM t1; +connect dml,localhost,root,,test; +SET DEBUG_SYNC='row_mysql_handle_errors SIGNAL s1 WAIT_FOR s2'; +UPDATE t1 SET c=1; +connection default; +SET DEBUG_SYNC='now WAIT_FOR s1'; +COMMIT; +connection stop_purge; +COMMIT; +disconnect stop_purge; +connection default; +InnoDB 0 transactions not purged +SET DEBUG_SYNC='now SIGNAL s2'; +connection dml; +disconnect dml; +connection default; +SET DEBUG_SYNC=RESET; +DROP TABLE t1; # 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 0431177a130..bbfe8a9fcd4 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -364,6 +364,44 @@ DROP TABLE t1; SET GLOBAL innodb_limit_optimistic_insert_debug = @saved_limit; +--echo # +--echo # MDEV-24620 ASAN heap-buffer-overflow in btr_pcur_restore_position() +--echo # + +CREATE TABLE t1 (a VARCHAR(1) PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +connect (stop_purge,localhost,root,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +ALTER TABLE t1 ADD c INT; +BEGIN; +DELETE FROM t1; + +connect (dml,localhost,root,,test); +SET DEBUG_SYNC='row_mysql_handle_errors SIGNAL s1 WAIT_FOR s2'; +send UPDATE t1 SET c=1; + +connection default; +SET DEBUG_SYNC='now WAIT_FOR s1'; +COMMIT; + +connection stop_purge; +COMMIT; +disconnect stop_purge; + +connection default; +--source include/wait_all_purged.inc +SET DEBUG_SYNC='now SIGNAL s2'; + +connection dml; +reap; +disconnect dml; + +connection default; +SET DEBUG_SYNC=RESET; +DROP TABLE t1; + --echo # End of 10.3 tests SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 2c5e7f96655..2842f9a6bc0 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2020, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -890,7 +890,7 @@ btr_page_get_father_node_ptr_func( node_ptr = btr_cur_get_rec(cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != page_no) { @@ -907,10 +907,11 @@ btr_page_get_father_node_ptr_func( print_rec = page_rec_get_next( page_get_infimum_rec(page_align(user_rec))); offsets = rec_get_offsets(print_rec, index, offsets, - page_rec_is_leaf(user_rec), + page_rec_is_leaf(user_rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); page_rec_print(print_rec, offsets); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); page_rec_print(node_ptr, offsets); @@ -2214,7 +2215,9 @@ btr_page_get_split_rec( incl_data += insert_size; } else { offsets = rec_get_offsets(rec, cursor->index, offsets, - page_is_leaf(page), + page_is_leaf(page) + ? cursor->index->n_core_fields + : 0, ULINT_UNDEFINED, &heap); incl_data += rec_offs_size(offsets); } @@ -2323,7 +2326,9 @@ btr_page_insert_fits( space after rec is removed from page. */ *offsets = rec_get_offsets(rec, cursor->index, *offsets, - page_is_leaf(page), + page_is_leaf(page) + ? cursor->index->n_core_fields + : 0, ULINT_UNDEFINED, heap); total_data -= rec_offs_size(*offsets); @@ -2610,7 +2615,8 @@ btr_page_tuple_smaller( first_rec = page_cur_get_rec(&pcur); *offsets = rec_get_offsets( - first_rec, cursor->index, *offsets, page_is_leaf(block->frame), + first_rec, cursor->index, *offsets, + page_is_leaf(block->frame) ? cursor->index->n_core_fields : 0, n_uniq, heap); return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0); @@ -2894,7 +2900,9 @@ func_start: first_rec = move_limit = split_rec; *offsets = rec_get_offsets(split_rec, cursor->index, *offsets, - page_is_leaf(page), n_uniq, heap); + page_is_leaf(page) + ? cursor->index->n_core_fields : 0, + n_uniq, heap); insert_left = !tuple || cmp_dtuple_rec(tuple, split_rec, *offsets) < 0; @@ -3665,7 +3673,7 @@ retry: rec_offs* offsets2 = NULL; /* For rtree, we need to update father's mbr. */ - if (dict_index_is_spatial(index)) { + if (index->is_spatial()) { /* We only support merge pages with the same parent page */ if (!rtr_check_same_block( @@ -3683,7 +3691,8 @@ retry: offsets2 = rec_get_offsets( btr_cur_get_rec(&cursor2), index, NULL, - page_is_leaf(cursor2.page_cur.block->frame), + page_is_leaf(cursor2.page_cur.block->frame) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); /* Check if parent entry needs to be updated */ @@ -3857,13 +3866,14 @@ retry: #endif /* UNIV_DEBUG */ /* For rtree, we need to update father's mbr. */ - if (dict_index_is_spatial(index)) { + if (index->is_spatial()) { rec_offs* offsets2; ulint rec_info; offsets2 = rec_get_offsets( btr_cur_get_rec(&cursor2), index, NULL, - page_is_leaf(cursor2.page_cur.block->frame), + page_is_leaf(cursor2.page_cur.block->frame) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); ut_ad(btr_node_ptr_get_child_page_no( @@ -4341,7 +4351,7 @@ btr_print_recursive( node_ptr = page_cur_get_rec(&cursor); *offsets = rec_get_offsets( - node_ptr, index, *offsets, false, + node_ptr, index, *offsets, 0, ULINT_UNDEFINED, heap); btr_print_recursive(index, btr_node_ptr_get_child(node_ptr, @@ -4490,7 +4500,9 @@ btr_index_rec_validate( page = page_align(rec); - if (dict_index_is_ibuf(index)) { + ut_ad(index->n_core_fields); + + if (index->is_ibuf()) { /* The insert buffer index tree can contain records from any other index: we cannot check the number of fields or their length */ @@ -4536,7 +4548,8 @@ btr_index_rec_validate( } } - offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); for (unsigned i = 0; i < index->n_fields; i++) { @@ -4792,7 +4805,7 @@ btr_validate_level( page_cur_move_to_next(&cursor); node_ptr = page_cur_get_rec(&cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); savepoint2 = mtr_set_savepoint(&mtr); @@ -4916,10 +4929,12 @@ loop: right_rec = page_rec_get_next(page_get_infimum_rec( right_page)); offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), + page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); offsets2 = rec_get_offsets(right_rec, index, offsets2, - page_is_leaf(right_page), + page_is_leaf(right_page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); /* For spatial index, we cannot guarantee the key ordering diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 69f605dc905..c05cf2a7b7a 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2019, 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 @@ -193,7 +193,8 @@ PageBulk::insert( if (!page_rec_is_infimum_low(page_offset(m_cur_rec))) { rec_t* old_rec = m_cur_rec; rec_offs* old_offsets = rec_get_offsets( - old_rec, m_index, NULL, is_leaf, + old_rec, m_index, NULL, is_leaf + ? m_index->n_core_fields : 0, ULINT_UNDEFINED, &m_heap); ut_ad(cmp_rec_rec(rec, old_rec, offsets, old_offsets, m_index) @@ -447,6 +448,7 @@ PageBulk::getSplitRec() ut_ad(m_page_zip != NULL); ut_ad(m_rec_no >= 2); + ut_ad(!m_index->is_instant()); ut_ad(page_get_free_space_of_empty(m_is_comp) > m_free_space); total_used_size = page_get_free_space_of_empty(m_is_comp) @@ -456,13 +458,13 @@ PageBulk::getSplitRec() n_recs = 0; offsets = NULL; rec = page_get_infimum_rec(m_page); + const ulint n_core = page_is_leaf(m_page) ? m_index->n_core_fields : 0; do { rec = page_rec_get_next(rec); ut_ad(page_rec_is_user_rec(rec)); - offsets = rec_get_offsets(rec, m_index, offsets, - page_is_leaf(m_page), + offsets = rec_get_offsets(rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); total_recs_size += rec_offs_size(offsets); n_recs++; @@ -491,9 +493,11 @@ PageBulk::copyIn( ut_ad(m_rec_no == 0); ut_ad(page_rec_is_user_rec(rec)); + const ulint n_core = page_rec_is_leaf(rec) + ? m_index->n_core_fields : 0; + do { - offsets = rec_get_offsets(rec, m_index, offsets, - page_rec_is_leaf(split_rec), + offsets = rec_get_offsets(rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); insert(rec, offsets); @@ -534,8 +538,10 @@ PageBulk::copyOut( /* Set last record's next in page */ rec_offs* offsets = NULL; rec = page_rec_get_prev(split_rec); - offsets = rec_get_offsets(rec, m_index, offsets, - page_rec_is_leaf(split_rec), + const ulint n_core = page_rec_is_leaf(split_rec) + ? m_index->n_core_fields : 0; + + offsets = rec_get_offsets(rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); page_rec_set_next(rec, page_get_supremum_rec(m_page)); @@ -543,8 +549,7 @@ PageBulk::copyOut( m_cur_rec = rec; m_heap_top = rec_get_end(rec, offsets); - offsets = rec_get_offsets(last_rec, m_index, offsets, - page_rec_is_leaf(split_rec), + offsets = rec_get_offsets(last_rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); m_free_space += ulint(rec_get_end(last_rec, offsets) - m_heap_top) @@ -975,7 +980,8 @@ BtrBulk::insert( /* Convert tuple to rec. */ rec = rec_convert_dtuple_to_rec(static_cast(mem_heap_alloc( page_bulk->m_heap, rec_size)), m_index, tuple, n_ext); - offsets = rec_get_offsets(rec, m_index, offsets, !level, + offsets = rec_get_offsets(rec, m_index, offsets, level + ? 0 : m_index->n_core_fields, ULINT_UNDEFINED, &page_bulk->m_heap); page_bulk->insert(rec, offsets); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index cb00d009973..45ba84e319c 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -479,7 +479,8 @@ incompatible: from the cache. */ mem_heap_t* heap = NULL; - rec_offs* offsets = rec_get_offsets(rec, index, NULL, true, + rec_offs* offsets = rec_get_offsets(rec, index, NULL, + index->n_core_fields, ULINT_UNDEFINED, &heap); if (rec_offs_any_default(offsets)) { inconsistent: @@ -1920,7 +1921,7 @@ retry_page_get: node_ptr = page_cur_get_rec(page_cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for @@ -2051,7 +2052,7 @@ need_opposite_intention: offsets2 = rec_get_offsets( first_rec, index, offsets2, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); cmp_rec_rec(node_ptr, first_rec, offsets, offsets2, index, false, &matched_fields); @@ -2069,7 +2070,7 @@ need_opposite_intention: offsets2 = rec_get_offsets( last_rec, index, offsets2, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); cmp_rec_rec( node_ptr, last_rec, offsets, offsets2, index, @@ -2238,7 +2239,7 @@ need_opposite_intention: offsets = rec_get_offsets( my_node_ptr, index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); ulint my_page_no = btr_node_ptr_get_child_page_no( @@ -2690,7 +2691,7 @@ btr_cur_open_at_index_side_func( node_ptr = page_cur_get_rec(page_cursor); offsets = rec_get_offsets(node_ptr, cursor->index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -2985,7 +2986,7 @@ btr_cur_open_at_rnd_pos_func( node_ptr = page_cur_get_rec(page_cursor); offsets = rec_get_offsets(node_ptr, cursor->index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -3932,7 +3933,8 @@ btr_cur_parse_update_in_place( flags != (BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG) - || page_is_leaf(page), + || page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (!(flags & BTR_KEEP_SYS_FLAG)) { @@ -4318,7 +4320,7 @@ btr_cur_optimistic_update( ut_ad(fil_page_index_page_check(page)); ut_ad(btr_page_get_index_id(page) == index->id); - *offsets = rec_get_offsets(rec, index, *offsets, true, + *offsets = rec_get_offsets(rec, index, *offsets, index->n_core_fields, ULINT_UNDEFINED, heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(rec, *offsets) @@ -5158,7 +5160,8 @@ btr_cur_parse_del_mark_set_clust_rec( if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_rec_sys_fields_in_recovery( rec, page_zip, - rec_get_offsets(rec, index, offsets, true, + rec_get_offsets(rec, index, offsets, + index->n_core_fields, pos + 2, &heap), pos, trx_id, roll_ptr); } else { @@ -5167,7 +5170,8 @@ btr_cur_parse_del_mark_set_clust_rec( ut_ad(memcmp(rec_get_nth_field( rec, rec_get_offsets(rec, index, - offsets, true, + offsets, index + ->n_core_fields, pos, &heap), pos, &offset), field_ref_zero, DATA_TRX_ID_LEN)); @@ -5502,7 +5506,8 @@ btr_cur_optimistic_delete_func( rec = btr_cur_get_rec(cursor); - offsets = rec_get_offsets(rec, cursor->index, offsets, true, + offsets = rec_get_offsets(rec, cursor->index, offsets, + cursor->index->n_core_fields, ULINT_UNDEFINED, &heap); const ibool no_compress_needed = !rec_offs_any_extern(offsets) @@ -5711,7 +5716,8 @@ btr_cur_pessimistic_delete( ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ - offsets = rec_get_offsets(rec, index, NULL, page_is_leaf(page), + offsets = rec_get_offsets(rec, index, NULL, page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (rec_offs_any_extern(offsets)) { @@ -5807,7 +5813,7 @@ discard_page: pointer as the predefined minimum record */ min_mark_next_rec = true; - } else if (dict_index_is_spatial(index)) { + } else if (index->is_spatial()) { /* For rtree, if delete the leftmost node pointer, we need to update parent page. */ rtr_mbr_t father_mbr; @@ -5822,7 +5828,7 @@ discard_page: &father_cursor); offsets = rec_get_offsets( btr_cur_get_rec(&father_cursor), index, NULL, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); father_rec = btr_cur_get_rec(&father_cursor); rtr_read_mbr(rec_get_nth_field( @@ -6744,12 +6750,13 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index) page = btr_cur_get_page(&cursor); rec = page_rec_get_next(page_get_infimum_rec(page)); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) + ? index->n_core_fields : 0; if (!page_rec_is_supremum(rec)) { not_empty_flag = 1; offsets_rec = rec_get_offsets(rec, index, offsets_rec, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); if (n_not_null != NULL) { @@ -6770,7 +6777,7 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index) offsets_next_rec = rec_get_offsets(next_rec, index, offsets_next_rec, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index 522c356fbb0..99b15965281 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2012, 2014 Facebook, Inc. All Rights Reserved. -Copyright (C) 2014, 2019, MariaDB Corporation. +Copyright (C) 2014, 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 @@ -340,12 +340,12 @@ btr_defragment_calc_n_recs_for_size( ulint size = 0; page_cur_t cur; + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; page_cur_set_before_first(block, &cur); page_cur_move_to_next(&cur); while (page_cur_get_rec(&cur) != page_get_supremum_rec(page)) { rec_t* cur_rec = page_cur_get_rec(&cur); - offsets = rec_get_offsets(cur_rec, index, offsets, - page_is_leaf(page), + offsets = rec_get_offsets(cur_rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); ulint rec_size = rec_offs_size(offsets); size += rec_size; @@ -357,6 +357,9 @@ btr_defragment_calc_n_recs_for_size( page_cur_move_to_next(&cur); } *n_recs_size = size; + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } return n_recs; } diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 9c6189acbce..ef626e12cf4 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -61,6 +61,7 @@ btr_pcur_reset( cursor->btr_cur.index = NULL; cursor->btr_cur.page_cur.rec = NULL; cursor->old_rec = NULL; + cursor->old_n_core_fields = 0; cursor->old_n_fields = 0; cursor->old_stored = false; @@ -178,9 +179,28 @@ before_first: cursor->rel_pos = BTR_PCUR_ON; } - cursor->old_rec = dict_index_copy_rec_order_prefix( - index, rec, &cursor->old_n_fields, - &cursor->old_rec_buf, &cursor->buf_size); + UNIV_PREFETCH_R(rec); + + if (index->is_ibuf()) { + cursor->old_n_fields = uint16(rec_get_n_fields_old(rec)); + } else { + cursor->old_n_fields = static_cast( + dict_index_get_n_unique_in_tree(index)); + if (index->is_spatial() && !page_rec_is_leaf(rec)) { + ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) + == DICT_INDEX_SPATIAL_NODEPTR_SIZE); + /* For R-tree, we have to compare + the child page numbers as well. */ + cursor->old_n_fields + = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; + } + } + + cursor->old_n_core_fields = index->n_core_fields; + cursor->old_rec = rec_copy_prefix_to_buf(rec, index, + cursor->old_n_fields, + &cursor->old_rec_buf, + &cursor->buf_size); cursor->block_when_stored.store(block); @@ -212,6 +232,7 @@ btr_pcur_copy_stored_position( + (pcur_donate->old_rec - pcur_donate->old_rec_buf); } + pcur_receive->old_n_core_fields = pcur_donate->old_n_core_fields; pcur_receive->old_n_fields = pcur_donate->old_n_fields; } @@ -303,6 +324,8 @@ btr_pcur_restore_position_func( } ut_a(cursor->old_rec); + ut_a(cursor->old_n_core_fields); + ut_a(cursor->old_n_core_fields <= index->n_core_fields); ut_a(cursor->old_n_fields); switch (latch_mode) { @@ -336,11 +359,16 @@ btr_pcur_restore_position_func( rec_offs_init(offsets2_); heap = mem_heap_create(256); + ut_ad(cursor->old_n_core_fields + == index->n_core_fields); + offsets1 = rec_get_offsets( - cursor->old_rec, index, offsets1, true, + cursor->old_rec, index, offsets1, + cursor->old_n_core_fields, cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, offsets2, true, + rec, index, offsets2, + index->n_core_fields, cursor->old_n_fields, &heap); ut_ad(!cmp_rec_rec(cursor->old_rec, @@ -365,8 +393,14 @@ btr_pcur_restore_position_func( heap = mem_heap_create(256); - tuple = dict_index_build_data_tuple(cursor->old_rec, index, true, - cursor->old_n_fields, heap); + tuple = dtuple_create(heap, cursor->old_n_fields); + + dict_index_copy_types(tuple, index, cursor->old_n_fields); + + rec_copy_prefix_to_dtuple(tuple, cursor->old_rec, index, + cursor->old_n_core_fields, + cursor->old_n_fields, heap); + ut_ad(dtuple_check_typed(tuple)); /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; @@ -405,7 +439,8 @@ btr_pcur_restore_position_func( && btr_pcur_is_on_user_rec(cursor) && !cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), rec_get_offsets(btr_pcur_get_rec(cursor), - index, offsets, true, + index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap))) { /* We have to store the NEW value for the modify clock, diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index b0b75ded890..1b8375d60fe 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -703,7 +703,8 @@ btr_search_update_hash_ref( ulint fold = rec_fold( rec, - rec_get_offsets(rec, index, offsets_, true, + rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, index->id); @@ -762,7 +763,8 @@ btr_search_check_guess( match = 0; - offsets = rec_get_offsets(rec, cursor->index, offsets, true, + offsets = rec_get_offsets(rec, cursor->index, offsets, + cursor->index->n_core_fields, n_unique, &heap); cmp = cmp_dtuple_rec_with_match(tuple, rec, offsets, &match); @@ -813,7 +815,8 @@ btr_search_check_guess( } offsets = rec_get_offsets(prev_rec, cursor->index, offsets, - true, n_unique, &heap); + cursor->index->n_core_fields, + n_unique, &heap); cmp = cmp_dtuple_rec_with_match( tuple, prev_rec, offsets, &match); if (mode == PAGE_CUR_GE) { @@ -836,7 +839,8 @@ btr_search_check_guess( } offsets = rec_get_offsets(next_rec, cursor->index, offsets, - true, n_unique, &heap); + cursor->index->n_core_fields, + n_unique, &heap); cmp = cmp_dtuple_rec_with_match( tuple, next_rec, offsets, &match); if (mode == PAGE_CUR_LE) { @@ -1202,7 +1206,7 @@ retry: while (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id); @@ -1428,7 +1432,7 @@ btr_search_build_page_hash_index( ut_a(index->id == btr_page_get_index_id(page)); offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); ut_ad(page_rec_is_supremum(rec) @@ -1459,7 +1463,7 @@ btr_search_build_page_hash_index( } offsets = rec_get_offsets( - next_rec, index, offsets, true, + next_rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, index->id); @@ -1699,7 +1703,8 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor) rec = btr_cur_get_rec(cursor); - fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, true, + fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, index->id); if (UNIV_LIKELY_NULL(heap)) { @@ -1876,13 +1881,14 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) ins_rec = page_rec_get_next_const(rec); next_rec = page_rec_get_next_const(ins_rec); - offsets = rec_get_offsets(ins_rec, index, offsets, true, + offsets = rec_get_offsets(ins_rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id); if (!page_rec_is_supremum(next_rec)) { offsets = rec_get_offsets( - next_rec, index, offsets, true, + next_rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, index->id); @@ -1894,7 +1900,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, index)) { offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id); } else { @@ -2100,7 +2106,8 @@ btr_search_hash_table_validate(ulint hash_table_id) page_index_id = btr_page_get_index_id(block->frame); offsets = rec_get_offsets( - node->data, block->index, offsets, true, + node->data, block->index, offsets, + block->index->n_core_fields, btr_search_get_n_fields(block->curr_n_fields, block->curr_n_bytes), &heap); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 1abcb2f9065..1f05eb80e5d 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -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 @@ -5035,7 +5035,9 @@ dict_index_build_node_ptr( dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4); - rec_copy_prefix_to_dtuple(tuple, rec, index, !level, n_unique, heap); + rec_copy_prefix_to_dtuple(tuple, rec, index, + level ? 0 : index->n_core_fields, + n_unique, heap); dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) | REC_STATUS_NODE_PTR); @@ -5044,46 +5046,6 @@ dict_index_build_node_ptr( return(tuple); } -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ -{ - ulint n; - - UNIV_PREFETCH_R(rec); - - if (dict_index_is_ibuf(index)) { - ut_ad(!dict_table_is_comp(index->table)); - n = rec_get_n_fields_old(rec); - } else { - if (page_rec_is_leaf(rec)) { - n = dict_index_get_n_unique_in_tree(index); - } else if (dict_index_is_spatial(index)) { - ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) - == DICT_INDEX_SPATIAL_NODEPTR_SIZE); - /* For R-tree, we have to compare - the child page numbers as well. */ - n = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; - } else { - n = dict_index_get_n_unique_in_tree(index); - } - } - - *n_fields = n; - return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size)); -} - /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index @@ -5099,11 +5061,14 @@ dict_index_build_data_tuple( ulint n_fields, mem_heap_t* heap) { + ut_ad(!index->is_clust()); + dtuple_t* tuple = dtuple_create(heap, n_fields); dict_index_copy_types(tuple, index, n_fields); - rec_copy_prefix_to_dtuple(tuple, rec, index, leaf, n_fields, heap); + rec_copy_prefix_to_dtuple(tuple, rec, index, + leaf ? n_fields : 0, n_fields, heap); ut_ad(dtuple_check_typed(tuple)); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index ea2f51d0f04..265642ef210 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -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 @@ -1544,7 +1544,8 @@ dict_index_t::vers_history_row( rec_t* clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, this, &clust_index, &mtr); if (clust_rec) { - offsets = rec_get_offsets(clust_rec, clust_index, offsets, true, + offsets = rec_get_offsets(clust_rec, clust_index, offsets, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); history_row = clust_index->vers_history_row(clust_rec, offsets); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index ba9ab056201..e36e2184e2d 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2009, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2020, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -1158,7 +1158,7 @@ dict_stats_analyze_index_level( prev_rec_offsets = rec_get_offsets( prev_rec, index, prev_rec_offsets, - true, + index->n_core_fields, n_uniq, &heap); prev_rec = rec_copy_prefix_to_buf( @@ -1170,8 +1170,9 @@ dict_stats_analyze_index_level( continue; } - rec_offsets = rec_get_offsets( - rec, index, rec_offsets, !level, n_uniq, &heap); + rec_offsets = rec_get_offsets(rec, index, rec_offsets, + level ? 0 : index->n_core_fields, + n_uniq, &heap); (*total_recs)++; @@ -1179,7 +1180,8 @@ dict_stats_analyze_index_level( ulint matched_fields; prev_rec_offsets = rec_get_offsets( - prev_rec, index, prev_rec_offsets, !level, + prev_rec, index, prev_rec_offsets, + level ? 0 : index->n_core_fields, n_uniq, &heap); cmp_rec_rec(prev_rec, rec, @@ -1333,7 +1335,7 @@ be big enough) @param[in] index index of the page @param[in] page the page to scan @param[in] n_prefix look at the first n_prefix columns -@param[in] is_leaf whether this is the leaf page +@param[in] n_core 0, or index->n_core_fields for leaf @param[out] n_diff number of distinct records encountered @param[out] n_external_pages if this is non-NULL then it will be set to the number of externally stored pages which were encountered @@ -1348,7 +1350,7 @@ dict_stats_scan_page( const dict_index_t* index, const page_t* page, ulint n_prefix, - bool is_leaf, + ulint n_core, ib_uint64_t* n_diff, ib_uint64_t* n_external_pages) { @@ -1360,9 +1362,9 @@ dict_stats_scan_page( Because offsets1,offsets2 should be big enough, this memory heap should never be used. */ mem_heap_t* heap = NULL; - ut_ad(is_leaf == page_is_leaf(page)); + ut_ad(!!n_core == page_is_leaf(page)); const rec_t* (*get_next)(const rec_t*) - = !is_leaf || srv_stats_include_delete_marked + = !n_core || srv_stats_include_delete_marked ? page_rec_get_next_const : page_rec_get_next_non_del_marked; @@ -1381,7 +1383,7 @@ dict_stats_scan_page( return(NULL); } - offsets_rec = rec_get_offsets(rec, index, offsets_rec, is_leaf, + offsets_rec = rec_get_offsets(rec, index, offsets_rec, n_core, ULINT_UNDEFINED, &heap); if (should_count_external_pages) { @@ -1398,7 +1400,7 @@ dict_stats_scan_page( ulint matched_fields; offsets_next_rec = rec_get_offsets(next_rec, index, - offsets_next_rec, is_leaf, + offsets_next_rec, n_core, ULINT_UNDEFINED, &heap); @@ -1412,7 +1414,7 @@ dict_stats_scan_page( (*n_diff)++; - if (!is_leaf) { + if (!n_core) { break; } } @@ -1498,7 +1500,7 @@ dict_stats_analyze_index_below_cur( rec = btr_cur_get_rec(cur); ut_ad(!page_rec_is_leaf(rec)); - offsets_rec = rec_get_offsets(rec, index, offsets1, false, + offsets_rec = rec_get_offsets(rec, index, offsets1, 0, ULINT_UNDEFINED, &heap); page_id_t page_id(index->table->space_id, @@ -1532,7 +1534,7 @@ dict_stats_analyze_index_below_cur( /* search for the first non-boring record on the page */ offsets_rec = dict_stats_scan_page( &rec, offsets1, offsets2, index, page, n_prefix, - false, n_diff, NULL); + 0, n_diff, NULL); /* pages on level > 0 are not allowed to be empty */ ut_a(offsets_rec != NULL); @@ -1577,7 +1579,7 @@ dict_stats_analyze_index_below_cur( offsets_rec = dict_stats_scan_page( &rec, offsets1, offsets2, index, page, n_prefix, - true, n_diff, + index->n_core_fields, n_diff, n_external_pages); #if 0 diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index c469055a763..ae60a6a9875 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, 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 @@ -3495,7 +3495,8 @@ fts_add_doc_by_id( } - offsets = rec_get_offsets(clust_rec, clust_index, NULL, true, + offsets = rec_get_offsets(clust_rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); for (ulint i = 0; i < num_idx; ++i) { @@ -3671,7 +3672,8 @@ fts_get_max_doc_id( ut_ad(!rec_is_metadata(rec, index)); offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &heap); + rec, index, offsets, index->n_core_fields, + ULINT_UNDEFINED, &heap); data = rec_get_nth_field(rec, offsets, 0, &len); @@ -5166,7 +5168,8 @@ fts_get_doc_id_from_rec( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &my_heap); + rec, index, offsets, index->n_core_fields, + ULINT_UNDEFINED, &my_heap); col_no = dict_col_get_index_pos( &table->cols[table->fts->doc_col], index); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index 31344372c80..3ac2fbc0093 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 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 @@ -87,8 +87,9 @@ rtr_page_split_initialize_nodes( stop = task + n_recs; rec = page_rec_get_next(page_get_infimum_rec(page)); - const bool is_leaf = page_is_leaf(page); - *offsets = rec_get_offsets(rec, cursor->index, *offsets, is_leaf, + const ulint n_core = page_is_leaf(page) + ? cursor->index->n_core_fields : 0; + *offsets = rec_get_offsets(rec, cursor->index, *offsets, n_core, n_uniq, &heap); source_cur = rec_get_nth_field(rec, *offsets, 0, &len); @@ -101,7 +102,7 @@ rtr_page_split_initialize_nodes( rec = page_rec_get_next(rec); *offsets = rec_get_offsets(rec, cursor->index, *offsets, - is_leaf, n_uniq, &heap); + n_core, n_uniq, &heap); source_cur = rec_get_nth_field(rec, *offsets, 0, &len); } @@ -308,7 +309,8 @@ rtr_update_mbr_field( page_zip = buf_block_get_page_zip(block); child = btr_node_ptr_get_child_page_no(rec, offsets); - const bool is_leaf = page_is_leaf(block->frame); + const ulint n_core = page_is_leaf(block->frame) + ? index->n_core_fields : 0; if (new_rec) { child_rec = new_rec; @@ -324,7 +326,7 @@ rtr_update_mbr_field( if (cursor2) { rec_t* del_rec = btr_cur_get_rec(cursor2); offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), - index, NULL, false, + index, NULL, 0, ULINT_UNDEFINED, &heap); del_page_no = btr_node_ptr_get_child_page_no(del_rec, offsets2); cur2_pos = page_rec_get_n_recs_before(btr_cur_get_rec(cursor2)); @@ -389,7 +391,7 @@ rtr_update_mbr_field( = page_rec_get_nth(page, cur2_pos); } offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), - index, NULL, false, + index, NULL, 0, ULINT_UNDEFINED, &heap); ut_ad(del_page_no == btr_node_ptr_get_child_page_no( cursor2->page_cur.rec, @@ -427,7 +429,7 @@ rtr_update_mbr_field( ut_ad(old_rec != insert_rec); page_cur_position(old_rec, block, &page_cur); - offsets2 = rec_get_offsets(old_rec, index, NULL, is_leaf, + offsets2 = rec_get_offsets(old_rec, index, NULL, n_core, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&page_cur, index, offsets2, mtr); @@ -457,7 +459,7 @@ update_mbr: cur2_rec = cursor2->page_cur.rec; offsets2 = rec_get_offsets(cur2_rec, index, NULL, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cur2_rec_info = rec_get_info_bits(cur2_rec, @@ -517,7 +519,7 @@ update_mbr: if (ins_suc) { btr_cur_position(index, insert_rec, block, cursor); offsets = rec_get_offsets(insert_rec, - index, offsets, is_leaf, + index, offsets, n_core, ULINT_UNDEFINED, &heap); } @@ -532,7 +534,7 @@ update_mbr: cur2_rec = btr_cur_get_rec(cursor2); offsets2 = rec_get_offsets(cur2_rec, index, NULL, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); /* If the cursor2 position is on a wrong rec, we @@ -546,7 +548,7 @@ update_mbr: while (!page_rec_is_supremum(cur2_rec)) { offsets2 = rec_get_offsets(cur2_rec, index, NULL, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cur2_pno = btr_node_ptr_get_child_page_no( @@ -834,7 +836,8 @@ rtr_split_page_move_rec_list( rec_move = static_cast(mem_heap_alloc( heap, sizeof (*rec_move) * max_to_move)); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) + ? index->n_core_fields : 0; /* Insert the recs in group 2 to new page. */ for (cur_split_node = node_array; @@ -844,10 +847,10 @@ rtr_split_page_move_rec_list( block, cur_split_node->key); offsets = rec_get_offsets(cur_split_node->key, - index, offsets, is_leaf, + index, offsets, n_core, ULINT_UNDEFINED, &heap); - ut_ad(!is_leaf || cur_split_node->key != first_rec); + ut_ad(!n_core || cur_split_node->key != first_rec); rec = page_cur_insert_rec_low( page_cur_get_rec(&new_page_cursor), @@ -882,7 +885,7 @@ rtr_split_page_move_rec_list( same temp-table in parallel. max_trx_id is ignored for temp tables because it not required for MVCC. */ - if (is_leaf && !index->table->is_temporary()) { + if (n_core && !index->table->is_temporary()) { page_update_max_trx_id(new_block, NULL, page_get_max_trx_id(page), mtr); @@ -935,7 +938,7 @@ rtr_split_page_move_rec_list( block, &page_cursor); offsets = rec_get_offsets( page_cur_get_rec(&page_cursor), index, - offsets, is_leaf, ULINT_UNDEFINED, + offsets, n_core, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&page_cursor, index, offsets, mtr); @@ -1134,6 +1137,9 @@ func_start: /* Update the lock table */ lock_rtr_move_rec_list(new_block, block, rec_move, moved); + const ulint n_core = page_level + ? 0 : cursor->index->n_core_fields; + /* Delete recs in first group from the new page. */ for (cur_split_node = rtr_split_node_array; cur_split_node < end_split_node - 1; ++cur_split_node) { @@ -1152,7 +1158,7 @@ func_start: *offsets = rec_get_offsets( page_cur_get_rec(page_cursor), - cursor->index, *offsets, !page_level, + cursor->index, *offsets, n_core, ULINT_UNDEFINED, heap); page_cur_delete_rec(page_cursor, @@ -1169,7 +1175,7 @@ func_start: block, page_cursor); *offsets = rec_get_offsets( page_cur_get_rec(page_cursor), - cursor->index, *offsets, !page_level, + cursor->index, *offsets, n_core, ULINT_UNDEFINED, heap); page_cur_delete_rec(page_cursor, cursor->index, *offsets, mtr); @@ -1398,7 +1404,8 @@ rtr_page_copy_rec_list_end_no_locks( rec_offs offsets_2[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets2 = offsets_2; ulint moved = 0; - bool is_leaf = page_is_leaf(new_page); + const ulint n_core = page_is_leaf(new_page) + ? index->n_core_fields : 0; rec_offs_init(offsets_1); rec_offs_init(offsets_2); @@ -1427,14 +1434,14 @@ rtr_page_copy_rec_list_end_no_locks( cur_rec = page_rec_get_next(cur_rec); } - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) { ulint cur_matched_fields = 0; int cmp; offsets2 = rec_get_offsets(cur_rec, index, offsets2, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cmp = cmp_rec_rec(cur1_rec, cur_rec, offsets1, offsets2, index, false, @@ -1446,7 +1453,7 @@ rtr_page_copy_rec_list_end_no_locks( /* Skip small recs. */ page_cur_move_to_next(&page_cur); cur_rec = page_cur_get_rec(&page_cur); - } else if (is_leaf) { + } else if (n_core) { if (rec_get_deleted_flag(cur1_rec, dict_table_is_comp(index->table))) { goto next; @@ -1469,7 +1476,7 @@ rtr_page_copy_rec_list_end_no_locks( cur_rec = page_cur_get_rec(&page_cur); - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur_rec, index, @@ -1525,7 +1532,8 @@ rtr_page_copy_rec_list_start_no_locks( rec_offs* offsets2 = offsets_2; page_cur_t page_cur; ulint moved = 0; - bool is_leaf = page_is_leaf(buf_block_get_frame(block)); + const ulint n_core = page_is_leaf(buf_block_get_frame(block)) + ? index->n_core_fields : 0; rec_offs_init(offsets_1); rec_offs_init(offsets_2); @@ -1545,14 +1553,14 @@ rtr_page_copy_rec_list_start_no_locks( cur_rec = page_rec_get_next(cur_rec); } - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) { ulint cur_matched_fields = 0; offsets2 = rec_get_offsets(cur_rec, index, offsets2, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); int cmp = cmp_rec_rec(cur1_rec, cur_rec, offsets1, offsets2, index, false, @@ -1565,7 +1573,7 @@ rtr_page_copy_rec_list_start_no_locks( /* Skip small recs. */ page_cur_move_to_next(&page_cur); cur_rec = page_cur_get_rec(&page_cur); - } else if (is_leaf) { + } else if (n_core) { if (rec_get_deleted_flag( cur1_rec, dict_table_is_comp(index->table))) { @@ -1589,7 +1597,7 @@ rtr_page_copy_rec_list_start_no_locks( cur_rec = page_cur_get_rec(&page_cur); - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur_rec, index, @@ -1743,7 +1751,7 @@ rtr_check_same_block( while (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets( - rec, index, NULL, false, ULINT_UNDEFINED, &heap); + rec, index, NULL, 0, ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(rec, offsets) == page_no) { btr_cur_position(index, rec, parentb, cursor); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index ff5cbcfa9aa..e5ba43faa0b 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, 2018, 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 @@ -530,8 +530,7 @@ rtr_compare_cursor_rec( rec = btr_cur_get_rec(cursor); - offsets = rec_get_offsets( - rec, index, NULL, false, ULINT_UNDEFINED, heap); + offsets = rec_get_offsets(rec, index, NULL, 0, ULINT_UNDEFINED, heap); return(btr_node_ptr_get_child_page_no(rec, offsets) == page_no); } @@ -836,7 +835,8 @@ rtr_page_get_father_node_ptr( user_rec = btr_cur_get_rec(cursor); ut_a(page_rec_is_user_rec(user_rec)); - offsets = rec_get_offsets(user_rec, index, offsets, !level, + offsets = rec_get_offsets(user_rec, index, offsets, + level ? 0 : index->n_fields, ULINT_UNDEFINED, &heap); rtr_get_mbr_from_rec(user_rec, offsets, &mbr); @@ -853,7 +853,7 @@ rtr_page_get_father_node_ptr( node_ptr = btr_cur_get_rec(cursor); ut_ad(!page_rec_is_comp(node_ptr) || rec_get_status(node_ptr) == REC_STATUS_NODE_PTR); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); ulint child_page = btr_node_ptr_get_child_page_no(node_ptr, offsets); @@ -871,13 +871,14 @@ rtr_page_get_father_node_ptr( print_rec = page_rec_get_next( page_get_infimum_rec(page_align(user_rec))); offsets = rec_get_offsets(print_rec, index, offsets, - page_rec_is_leaf(user_rec), + page_rec_is_leaf(user_rec) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); error << "; child "; rec_print(error.m_oss, print_rec, rec_get_info_bits(print_rec, rec_offs_comp(offsets)), offsets); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); error << "; parent "; rec_print(error.m_oss, print_rec, @@ -1323,10 +1324,12 @@ rtr_cur_restore_position( heap = mem_heap_create(256); offsets1 = rec_get_offsets( - r_cursor->old_rec, index, NULL, !level, + r_cursor->old_rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, r_cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, NULL, !level, + rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, r_cursor->old_n_fields, &heap); comp = rec_offs_comp(offsets1); @@ -1394,12 +1397,12 @@ search_again: rec = btr_pcur_get_rec(r_cursor); - offsets1 = rec_get_offsets( - r_cursor->old_rec, index, NULL, !level, - r_cursor->old_n_fields, &heap); - offsets2 = rec_get_offsets( - rec, index, NULL, !level, - r_cursor->old_n_fields, &heap); + offsets1 = rec_get_offsets(r_cursor->old_rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, + r_cursor->old_n_fields, &heap); + offsets2 = rec_get_offsets(rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, + r_cursor->old_n_fields, &heap); comp = rec_offs_comp(offsets1); @@ -1689,7 +1692,7 @@ rtr_cur_search_with_match( page = buf_block_get_frame(block); const ulint level = btr_page_get_level(page); - const bool is_leaf = !level; + const ulint n_core = level ? 0 : index->n_fields; if (mode == PAGE_CUR_RTREE_LOCATE) { ut_ad(level != 0); @@ -1711,7 +1714,7 @@ rtr_cur_search_with_match( ulint new_rec_size = rec_get_converted_size(index, tuple, 0); - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); @@ -1732,10 +1735,10 @@ rtr_cur_search_with_match( } while (!page_rec_is_supremum(rec)) { - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); - if (!is_leaf) { + if (!n_core) { switch (mode) { case PAGE_CUR_CONTAIN: case PAGE_CUR_INTERSECT: @@ -1816,7 +1819,7 @@ rtr_cur_search_with_match( to rtr_info->path for non-leaf nodes, or rtr_info->matches for leaf nodes */ if (rtr_info && mode != PAGE_CUR_RTREE_INSERT) { - if (!is_leaf) { + if (!n_core) { ulint page_no; node_seq_t new_seq; bool is_loc; @@ -1827,7 +1830,7 @@ rtr_cur_search_with_match( == PAGE_CUR_RTREE_GET_FATHER); offsets = rec_get_offsets( - rec, index, offsets, false, + rec, index, offsets, 0, ULINT_UNDEFINED, &heap); page_no = btr_node_ptr_get_child_page_no( @@ -1876,7 +1879,8 @@ rtr_cur_search_with_match( /* Collect matched records on page */ offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, + index->n_fields, ULINT_UNDEFINED, &heap); rtr_leaf_push_match_rec( rec, rtr_info, offsets, @@ -1899,7 +1903,7 @@ rtr_cur_search_with_match( /* All records on page are searched */ if (page_rec_is_supremum(rec)) { - if (!is_leaf) { + if (!n_core) { if (!found) { /* No match case, if it is for insertion, then we select the record that result in @@ -1909,7 +1913,7 @@ rtr_cur_search_with_match( ut_ad(least_inc < DBL_MAX); offsets = rec_get_offsets( best_rec, index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); child_no = btr_node_ptr_get_child_page_no( best_rec, offsets); @@ -1961,11 +1965,11 @@ rtr_cur_search_with_match( /* Verify the record to be positioned is the same as the last record in matched_rec vector */ offsets2 = rec_get_offsets(test_rec.r_rec, index, - offsets2, true, + offsets2, index->n_fields, ULINT_UNDEFINED, &heap); offsets = rec_get_offsets(last_match_rec, index, - offsets, true, + offsets, index->n_fields, ULINT_UNDEFINED, &heap); ut_ad(cmp_rec_rec(test_rec.r_rec, last_match_rec, @@ -1982,9 +1986,8 @@ rtr_cur_search_with_match( ulint child_no; ut_ad(!last_match_rec && rec); - offsets = rec_get_offsets( - rec, index, offsets, false, - ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, 0, + ULINT_UNDEFINED, &heap); child_no = btr_node_ptr_get_child_page_no(rec, offsets); @@ -1992,7 +1995,7 @@ rtr_cur_search_with_match( index, rtr_info->parent_path, level, child_no, block, rec, 0); - } else if (rtr_info && found && !is_leaf) { + } else if (rtr_info && found && !n_core) { rec = last_match_rec; } @@ -2002,11 +2005,11 @@ rtr_cur_search_with_match( #ifdef UNIV_DEBUG /* Verify that we are positioned at the same child page as pushed in the path stack */ - if (!is_leaf && (!page_rec_is_supremum(rec) || found) + if (!n_core && (!page_rec_is_supremum(rec) || found) && mode != PAGE_CUR_RTREE_INSERT) { ulint page_no; - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); page_no = btr_node_ptr_get_child_page_no(rec, offsets); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index f517b49c999..4bebb7d1257 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -3906,7 +3906,7 @@ dump: row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */ ut_ad(rec_get_deleted_flag(rec, page_is_comp(page))); - offsets = rec_get_offsets(rec, index, NULL, true, + offsets = rec_get_offsets(rec, index, NULL, index->n_fields, ULINT_UNDEFINED, &heap); update = row_upd_build_sec_rec_difference_binary( rec, index, offsets, entry, heap); @@ -4079,7 +4079,8 @@ ibuf_delete( ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); - ut_ad(!dict_index_is_spatial(index)); + ut_ad(!index->is_spatial()); + ut_ad(!index->is_clust()); low_match = page_cur_search(block, index, entry, &page_cur); @@ -4098,8 +4099,8 @@ ibuf_delete( rec_offs_init(offsets_); - offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, + ULINT_UNDEFINED, &heap); if (page_get_n_recs(page) <= 1 || !(REC_INFO_DELETED_FLAG diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index 38960b1d15c..b0b61a4d1ff 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.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 @@ -497,8 +497,10 @@ struct btr_pcur_t{ /** if cursor position is stored, contains an initial segment of the latest record cursor was positioned either on, before or after */ rec_t* old_rec; + /** btr_cur.index->n_core_fields when old_rec was copied */ + uint16 old_n_core_fields; /** number of fields in old_rec */ - ulint old_n_fields; + uint16 old_n_fields; /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on whether cursor was on, before, or after the old_rec record */ enum btr_pcur_pos_t rel_pos; diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 1c6dbcd3580..37eae6641af 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -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 @@ -1348,21 +1348,6 @@ dict_index_build_node_ptr( ulint level) /*!< in: level of rec in tree: 0 means leaf level */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 8fc82955b73..40c343652fb 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -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 @@ -1070,6 +1070,15 @@ struct dict_index_t{ return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF)); } + /** @return whether this is a generated clustered index */ + bool is_gen_clust() const { return type == DICT_CLUSTERED; } + + /** @return whether this is a clustered index */ + bool is_clust() const { return type & DICT_CLUSTERED; } + + /** @return whether this is a unique index */ + bool is_unique() const { return type & DICT_UNIQUE; } + /** @return whether this is a spatial index */ bool is_spatial() const { return UNIV_UNLIKELY(type & DICT_SPATIAL); } diff --git a/storage/innobase/include/gis0rtree.ic b/storage/innobase/include/gis0rtree.ic index a22164931b2..89676fb2386 100644 --- a/storage/innobase/include/gis0rtree.ic +++ b/storage/innobase/include/gis0rtree.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 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 @@ -57,7 +57,8 @@ rtr_page_cal_mbr( page = buf_block_get_frame(block); rec = page_rec_get_next(page_get_infimum_rec(page)); - offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); do { diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index 4d7b5c3a42f..7896aa64792 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -278,7 +278,8 @@ page_cur_tuple_insert( index, tuple, n_ext); *offsets = rec_get_offsets(rec, index, *offsets, - page_is_leaf(cursor->block->frame), + page_is_leaf(cursor->block->frame) + ? index->n_core_fields : 0, ULINT_UNDEFINED, heap); if (buf_block_get_page_zip(cursor->block)) { diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 41980cde2c8..7d7af9e2beb 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 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 @@ -554,7 +554,7 @@ rec_get_n_extern_new( @param[in] index the index that the record belongs to @param[in,out] offsets array comprising offsets[0] allocated elements, or an array from rec_get_offsets(), or NULL -@param[in] leaf whether this is a leaf-page record +@param[in] n_core 0, or index->n_core_fields for leaf page @param[in] n_fields maximum number of offsets to compute (ULINT_UNDEFINED to compute all offsets) @param[in,out] heap memory heap @@ -564,7 +564,7 @@ rec_get_offsets_func( const rec_t* rec, const dict_index_t* index, rec_offs* offsets, - bool leaf, + ulint n_core, ulint n_fields, #ifdef UNIV_DEBUG const char* file, /*!< in: file name where called */ @@ -1121,7 +1121,9 @@ rec_get_converted_size( The fields are copied into the memory heap. @param[out] tuple data tuple @param[in] rec index record, or a copy thereof -@param[in] is_leaf whether rec is a leaf page record +@param[in] index index of rec +@param[in] n_core index->n_core_fields at the time rec was + copied, or 0 if non-leaf page record @param[in] n_fields number of fields to copy @param[in,out] heap memory heap */ void @@ -1129,7 +1131,7 @@ rec_copy_prefix_to_dtuple( dtuple_t* tuple, const rec_t* rec, const dict_index_t* index, - bool is_leaf, + ulint n_core, ulint n_fields, mem_heap_t* heap) MY_ATTRIBUTE((nonnull)); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index bd09f3b81ca..b3086842624 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4486,7 +4486,8 @@ static void lock_rec_print(FILE* file, const lock_t* lock, mtr_t& mtr) ut_ad(!page_rec_is_metadata(rec)); offsets = rec_get_offsets( - rec, lock->index, offsets, true, + rec, lock->index, offsets, + lock->index->n_core_fields, ULINT_UNDEFINED, &heap); putc(' ', file); @@ -5032,8 +5033,8 @@ loop: ut_ad(!lock_rec_get_nth_bit(lock, i) || page_rec_is_leaf(rec)); offsets = rec_get_offsets(rec, lock->index, offsets, - true, ULINT_UNDEFINED, - &heap); + lock->index->n_core_fields, + ULINT_UNDEFINED, &heap); /* If this thread is holding the file space latch (fil_space_t::latch), the following @@ -5364,7 +5365,8 @@ lock_rec_insert_check_and_lock( const rec_offs* offsets; rec_offs_init(offsets_); - offsets = rec_get_offsets(next_rec, index, offsets_, true, + offsets = rec_get_offsets(next_rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate( @@ -5704,7 +5706,8 @@ lock_sec_rec_modify_check_and_lock( const rec_offs* offsets; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate( @@ -5916,7 +5919,7 @@ lock_clust_rec_read_check_and_lock_alt( rec_offs_init(offsets_); ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); err = lock_clust_rec_read_check_and_lock(flags, block, rec, index, offsets, mode, gap_mode, thr); diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index cf3ffe671ed..e4007fca83b 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 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 @@ -75,7 +75,7 @@ page_cur_try_search_shortcut( ut_ad(page_is_leaf(page)); rec = page_header_get_ptr(page, PAGE_LAST_INSERT); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, dtuple_get_n_fields(tuple), &heap); ut_ad(rec); @@ -90,7 +90,8 @@ page_cur_try_search_shortcut( next_rec = page_rec_get_next_const(rec); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, index, offsets, true, + offsets = rec_get_offsets(next_rec, index, offsets, + index->n_core_fields, dtuple_get_n_fields(tuple), &heap); if (cmp_dtuple_rec_with_match(tuple, next_rec, offsets, @@ -159,7 +160,7 @@ page_cur_try_search_shortcut_bytes( ut_ad(page_is_leaf(page)); rec = page_header_get_ptr(page, PAGE_LAST_INSERT); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, dtuple_get_n_fields(tuple), &heap); ut_ad(rec); @@ -180,7 +181,8 @@ page_cur_try_search_shortcut_bytes( next_rec = page_rec_get_next_const(rec); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, index, offsets, true, + offsets = rec_get_offsets(next_rec, index, offsets, + index->n_core_fields, dtuple_get_n_fields(tuple), &heap); if (cmp_dtuple_rec_with_match_bytes( @@ -321,14 +323,14 @@ page_cur_search_with_match( #endif /* UNIV_ZIP_DEBUG */ ut_d(page_check_dir(page)); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; #ifdef BTR_CUR_HASH_ADAPT - if (is_leaf + if (n_core && page_get_direction(page) == PAGE_RIGHT && page_header_get_offs(page, PAGE_LAST_INSERT) && mode == PAGE_CUR_LE - && !dict_index_is_spatial(index) + && !index->is_spatial() && page_header_get_field(page, PAGE_N_DIRECTION) > 3 && page_cur_try_search_shortcut( block, index, tuple, @@ -344,10 +346,10 @@ page_cur_search_with_match( /* If the mode is for R-tree indexes, use the special MBR related compare functions */ - if (dict_index_is_spatial(index) && mode > PAGE_CUR_LE) { + if (index->is_spatial() && mode > PAGE_CUR_LE) { /* For leaf level insert, we still use the traditional compare function for now */ - if (mode == PAGE_CUR_RTREE_INSERT && is_leaf) { + if (mode == PAGE_CUR_RTREE_INSERT && n_core) { mode = PAGE_CUR_LE; } else { rtr_cur_search_with_match( @@ -392,7 +394,7 @@ page_cur_search_with_match( offsets = offsets_; offsets = rec_get_offsets( - mid_rec, index, offsets, is_leaf, + mid_rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match( @@ -446,7 +448,7 @@ up_slot_match: offsets = offsets_; offsets = rec_get_offsets( - mid_rec, index, offsets, is_leaf, + mid_rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match( @@ -627,7 +629,7 @@ page_cur_search_with_match_bytes( /* Perform binary search until the lower and upper limit directory slots come to the distance 1 of each other */ - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; while (up - low > 1) { mid = (low + up) / 2; @@ -639,7 +641,7 @@ page_cur_search_with_match_bytes( up_matched_fields, up_matched_bytes); offsets = rec_get_offsets( - mid_rec, index, offsets_, is_leaf, + mid_rec, index, offsets_, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match_bytes( @@ -707,7 +709,7 @@ up_slot_match: } offsets = rec_get_offsets( - mid_rec, index, offsets_, is_leaf, + mid_rec, index, offsets_, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match_bytes( @@ -817,7 +819,8 @@ page_cur_insert_rec_write_log( ut_ad(!page_rec_is_comp(insert_rec) == !dict_table_is_comp(index->table)); - const bool is_leaf = page_rec_is_leaf(cursor_rec); + const ulint n_core = page_rec_is_leaf(cursor_rec) + ? index->n_core_fields : 0; { mem_heap_t* heap = NULL; @@ -831,9 +834,9 @@ page_cur_insert_rec_write_log( rec_offs_init(ins_offs_); cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_, - is_leaf, ULINT_UNDEFINED, &heap); + n_core, ULINT_UNDEFINED, &heap); ins_offs = rec_get_offsets(insert_rec, index, ins_offs_, - is_leaf, ULINT_UNDEFINED, &heap); + n_core, ULINT_UNDEFINED, &heap); extra_size = rec_offs_extra_size(ins_offs); cur_extra_size = rec_offs_extra_size(cur_offs); @@ -1091,9 +1094,9 @@ page_cur_parse_insert_rec( /* Read from the log the inserted index record end segment which differs from the cursor record */ - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; - offsets = rec_get_offsets(cursor_rec, index, offsets, is_leaf, + offsets = rec_get_offsets(cursor_rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (!(end_seg_len & 0x1UL)) { @@ -1142,7 +1145,7 @@ page_cur_parse_insert_rec( page_cur_position(cursor_rec, block, &cursor); offsets = rec_get_offsets(buf + origin_offset, index, offsets, - is_leaf, ULINT_UNDEFINED, &heap); + n_core, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr))) { @@ -1323,7 +1326,8 @@ page_cur_insert_rec_low( rec_offs_init(foffsets_); foffsets = rec_get_offsets( - free_rec, index, foffsets, page_is_leaf(page), + free_rec, index, foffsets, + page_is_leaf(page) ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (rec_offs_size(foffsets) < rec_size) { if (UNIV_LIKELY_NULL(heap)) { @@ -1736,7 +1740,8 @@ page_cur_insert_rec_zip( rec_offs_init(foffsets_); foffsets = rec_get_offsets(free_rec, index, foffsets, - page_rec_is_leaf(free_rec), + page_rec_is_leaf(free_rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (rec_offs_size(foffsets) < rec_size) { too_small: @@ -2103,10 +2108,11 @@ page_copy_rec_list_end_to_created_page( slot_index = 0; n_recs = 0; - const bool is_leaf = page_is_leaf(new_page); + const ulint n_core = page_is_leaf(new_page) + ? index->n_core_fields : 0; do { - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); insert_rec = rec_copy(heap_top, rec, offsets); @@ -2148,7 +2154,7 @@ page_copy_rec_list_end_to_created_page( heap_top += rec_size; - rec_offs_make_valid(insert_rec, index, is_leaf, offsets); + rec_offs_make_valid(insert_rec, index, n_core != 0, offsets); page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec, index, mtr); prev_rec = insert_rec; @@ -2285,7 +2291,8 @@ page_cur_parse_delete_rec( page_cur_delete_rec(&cursor, index, rec_get_offsets(rec, index, offsets_, - page_rec_is_leaf(rec), + page_rec_is_leaf(rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap), mtr); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 38796d8cb8d..d69fdc7a202 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -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 @@ -560,7 +560,8 @@ page_copy_rec_list_end_no_locks( ut_a(page_is_comp(new_page) == page_rec_is_comp(rec)); ut_a(mach_read_from_2(new_page + srv_page_size - 10) == (ulint) (page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM)); - const bool is_leaf = page_is_leaf(block->frame); + const ulint n_core = page_is_leaf(block->frame) + ? index->n_core_fields : 0; cur2 = page_get_infimum_rec(buf_block_get_frame(new_block)); @@ -568,7 +569,7 @@ page_copy_rec_list_end_no_locks( while (!page_cur_is_after_last(&cur1)) { rec_t* ins_rec; - offsets = rec_get_offsets(cur1.rec, index, offsets, is_leaf, + offsets = rec_get_offsets(cur1.rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur2, index, cur1.rec, offsets, mtr); @@ -800,7 +801,7 @@ page_copy_rec_list_start( cur2 = ret; - const bool is_leaf = page_rec_is_leaf(rec); + const ulint n_core = page_rec_is_leaf(rec) ? index->n_core_fields : 0; /* Copy records from the original page to the new page */ if (index->is_spatial()) { @@ -822,7 +823,7 @@ page_copy_rec_list_start( } else { while (page_cur_get_rec(&cur1) != rec) { offsets = rec_get_offsets(cur1.rec, index, offsets, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cur2 = page_cur_insert_rec_low(cur2, index, cur1.rec, offsets, mtr); @@ -842,7 +843,7 @@ page_copy_rec_list_start( same temp-table in parallel. max_trx_id is ignored for temp tables because it not required for MVCC. */ - if (is_leaf && dict_index_is_sec_or_ibuf(index) + if (n_core && dict_index_is_sec_or_ibuf(index) && !index->table->is_temporary()) { page_update_max_trx_id(new_block, NULL, page_get_max_trx_id(page_align(rec)), @@ -1073,7 +1074,7 @@ delete_all: ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; if (page_zip) { mtr_log_t log_mode; @@ -1087,7 +1088,7 @@ delete_all: page_cur_t cur; page_cur_position(rec, block, &cur); - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); rec = rec_get_next_ptr(rec, TRUE); #ifdef UNIV_ZIP_DEBUG @@ -1120,8 +1121,7 @@ delete_all: do { ulint s; - offsets = rec_get_offsets(rec2, index, offsets, - is_leaf, + offsets = rec_get_offsets(rec2, index, offsets, n_core, ULINT_UNDEFINED, &heap); s = rec_offs_size(offsets); ut_ad(ulint(rec2 - page) + s @@ -1267,11 +1267,12 @@ page_delete_rec_list_start( /* Individual deletes are not logged */ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); - const bool is_leaf = page_rec_is_leaf(rec); + const ulint n_core = page_rec_is_leaf(rec) + ? index->n_core_fields : 0; while (page_cur_get_rec(&cur1) != rec) { offsets = rec_get_offsets(page_cur_get_rec(&cur1), index, - offsets, is_leaf, + offsets, n_core, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&cur1, index, offsets, mtr); } @@ -2482,9 +2483,10 @@ wrong_page_type: rec = page_get_infimum_rec(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; + for (;;) { - offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (page_is_comp(page) && page_rec_is_user_rec(rec) @@ -2732,8 +2734,7 @@ n_owned_zero: rec = page_header_get_ptr(page, PAGE_FREE); while (rec != NULL) { - offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) { ret = FALSE; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 382d4d5eeb3..d9146407833 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2020, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -881,7 +881,7 @@ page_zip_compress_node_ptrs( do { const rec_t* rec = *recs++; - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); /* Only leaf nodes may contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); @@ -1130,7 +1130,7 @@ page_zip_compress_clust( do { const rec_t* rec = *recs++; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, ULINT_UNDEFINED, &heap); ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index)); @@ -2052,7 +2052,7 @@ page_zip_apply_log( sorted by address (indexed by heap_no - PAGE_HEAP_NO_USER_LOW) */ ulint n_dense,/*!< in: size of recs[] */ - bool is_leaf,/*!< in: whether this is a leaf page */ + ulint n_core, /*!< in: index->n_fields, or 0 for non-leaf */ ulint trx_id_col,/*!< in: column number of trx_id in the index, or ULINT_UNDEFINED if none */ ulint heap_status, @@ -2128,7 +2128,7 @@ page_zip_apply_log( /* Clear the data bytes of the record. */ mem_heap_t* heap = NULL; rec_offs* offs; - offs = rec_get_offsets(rec, index, offsets, is_leaf, + offs = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); memset(rec, 0, rec_offs_data_size(offs)); @@ -2142,7 +2142,7 @@ page_zip_apply_log( rec_get_offsets_reverse(data, index, hs & REC_STATUS_NODE_PTR, offsets); - rec_offs_make_valid(rec, index, is_leaf, offsets); + rec_offs_make_valid(rec, index, n_core != 0, offsets); /* Copy the extra bytes (backwards). */ { @@ -2322,7 +2322,7 @@ page_zip_decompress_node_ptrs( } /* Read the offsets. The status bits are needed here. */ - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); /* Non-leaf nodes should not have any externally @@ -2409,7 +2409,7 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, false, + recs, n_dense, 0, ULINT_UNDEFINED, heap_status, index, offsets); @@ -2440,7 +2440,7 @@ zlib_done: for (slot = 0; slot < n_dense; slot++) { rec_t* rec = recs[slot]; - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); /* Non-leaf nodes should not have any externally stored columns. */ @@ -2562,7 +2562,8 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, true, + recs, n_dense, + index->n_fields, ULINT_UNDEFINED, heap_status, index, offsets); @@ -2765,7 +2766,7 @@ page_zip_decompress_clust( } /* Read the offsets. The status bits are needed here. */ - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, ULINT_UNDEFINED, &heap); /* This is a leaf page in a clustered index. */ @@ -2892,7 +2893,8 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, true, + recs, n_dense, + index->n_fields, trx_id_col, heap_status, index, offsets); @@ -2928,7 +2930,7 @@ zlib_done: rec_t* rec = recs[slot]; bool exists = !page_zip_dir_find_free( page_zip, page_offset(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, ULINT_UNDEFINED, &heap); dst = rec_get_nth_field(rec, offsets, @@ -3452,7 +3454,7 @@ page_zip_validate_low( page + PAGE_NEW_INFIMUM, TRUE); trec = page_rec_get_next_low( temp_page + PAGE_NEW_INFIMUM, TRUE); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_fields : 0; do { if (page_offset(rec) != page_offset(trec)) { @@ -3467,7 +3469,7 @@ page_zip_validate_low( if (index) { /* Compare the data. */ offsets = rec_get_offsets( - rec, index, offsets, is_leaf, + rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (memcmp(rec - rec_offs_extra_size(offsets), diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index c81e0031557..221e1f46b4f 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, 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 @@ -290,9 +290,9 @@ rec_init_offsets_comp_ordinary( ulint n_fields = n_core; ulint null_mask = 1; - ut_ad(index->n_core_fields >= n_core); ut_ad(n_core > 0); - ut_ad(index->n_fields >= n_core); + ut_ad(index->n_core_fields >= n_core); + ut_ad(index->n_fields >= index->n_core_fields); ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); ut_ad(format == REC_LEAF_TEMP || format == REC_LEAF_TEMP_COLUMNS_ADDED || dict_table_is_comp(index->table)); @@ -300,6 +300,11 @@ rec_init_offsets_comp_ordinary( || index->n_fields == rec_offs_n_fields(offsets)); ut_d(ulint n_null= 0); + const unsigned n_core_null_bytes = UNIV_UNLIKELY(index->n_core_fields + != n_core) + ? UT_BITS_IN_BYTES(unsigned(index->get_n_nullable(n_core))) + : index->n_core_null_bytes; + switch (format) { case REC_LEAF_TEMP: if (dict_table_is_comp(index->table)) { @@ -311,9 +316,9 @@ rec_init_offsets_comp_ordinary( case REC_LEAF_ORDINARY: nulls -= REC_N_NEW_EXTRA_BYTES; ordinary: - lens = --nulls - index->n_core_null_bytes; + lens = --nulls - n_core_null_bytes; - ut_d(n_null = std::min(index->n_core_null_bytes * 8U, + ut_d(n_null = std::min(n_core_null_bytes * 8U, index->n_nullable)); break; case REC_LEAF_COLUMNS_ADDED: @@ -329,7 +334,7 @@ ordinary: const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable); ut_d(n_null = n_nullable); ut_ad(n_null <= index->n_nullable); - ut_ad(n_null_bytes >= index->n_core_null_bytes + ut_ad(n_null_bytes >= n_core_null_bytes || n_core < index->n_core_fields); lens = --nulls - n_null_bytes; } @@ -559,14 +564,14 @@ is (SQL_NULL), the field i is NULL. When the type of the offset at [i+1] is (STORED_OFFPAGE), the field i is stored externally. @param[in] rec record @param[in] index the index that the record belongs in -@param[in] leaf whether the record resides in a leaf page +@param[in] n_core 0, or index->n_core_fields for leaf page @param[in,out] offsets array of offsets, with valid rec_offs_n_fields() */ static void rec_init_offsets( const rec_t* rec, const dict_index_t* index, - bool leaf, + ulint n_core, rec_offs* offsets) { ulint i = 0; @@ -575,6 +580,8 @@ rec_init_offsets( ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); ut_d(memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec))); ut_d(memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index))); + ut_ad(index->n_fields >= n_core); + ut_ad(index->n_core_fields >= n_core); if (dict_table_is_comp(index->table)) { const byte* nulls; @@ -593,23 +600,21 @@ rec_init_offsets( rec_offs_base(offsets)[1] = 8; return; case REC_STATUS_NODE_PTR: - ut_ad(!leaf); + ut_ad(!n_core); n_node_ptr_field = dict_index_get_n_unique_in_tree_nonleaf( index); break; case REC_STATUS_COLUMNS_ADDED: - ut_ad(leaf); ut_ad(index->is_instant()); rec_init_offsets_comp_ordinary(rec, index, offsets, - index->n_core_fields, + n_core, NULL, REC_LEAF_COLUMNS_ADDED); return; case REC_STATUS_ORDINARY: - ut_ad(leaf); rec_init_offsets_comp_ordinary(rec, index, offsets, - index->n_core_fields, + n_core, NULL, REC_LEAF_ORDINARY); return; @@ -766,7 +771,7 @@ resolved: @param[in] index the index that the record belongs to @param[in,out] offsets array comprising offsets[0] allocated elements, or an array from rec_get_offsets(), or NULL -@param[in] leaf whether this is a leaf-page record +@param[in] n_core 0, or index->n_core_fields for leaf page @param[in] n_fields maximum number of offsets to compute (ULINT_UNDEFINED to compute all offsets) @param[in,out] heap memory heap @@ -776,7 +781,7 @@ rec_get_offsets_func( const rec_t* rec, const dict_index_t* index, rec_offs* offsets, - bool leaf, + ulint n_core, ulint n_fields, #ifdef UNIV_DEBUG const char* file, /*!< in: file name where called */ @@ -787,19 +792,22 @@ rec_get_offsets_func( ulint n; ulint size; + ut_ad(index->n_core_fields >= n_core); + ut_ad(index->n_fields >= index->n_core_fields); + if (dict_table_is_comp(index->table)) { switch (UNIV_EXPECT(rec_get_status(rec), REC_STATUS_ORDINARY)) { case REC_STATUS_COLUMNS_ADDED: case REC_STATUS_ORDINARY: - ut_ad(leaf); + ut_ad(n_core); n = dict_index_get_n_fields(index); break; case REC_STATUS_NODE_PTR: /* Node pointer records consist of the uniquely identifying fields of the record followed by a child page number field. */ - ut_ad(!leaf); + ut_ad(!n_core); n = dict_index_get_n_unique_in_tree_nonleaf(index) + 1; break; case REC_STATUS_INFIMUM: @@ -828,18 +836,18 @@ rec_get_offsets_func( >= PAGE_HEAP_NO_USER_LOW; /* The infimum and supremum records carry 1 field. */ ut_ad(is_user_rec || n == 1); - ut_ad(!is_user_rec || leaf || index->is_dummy + ut_ad(!is_user_rec || n_core || index->is_dummy || dict_index_is_ibuf(index) || n == n_fields /* dict_stats_analyze_index_level() */ || n == dict_index_get_n_unique_in_tree_nonleaf(index) + 1); - ut_ad(!is_user_rec || !leaf || index->is_dummy + ut_ad(!is_user_rec || !n_core || index->is_dummy || dict_index_is_ibuf(index) || n == n_fields /* btr_pcur_restore_position() */ || (n + (index->id == DICT_INDEXES_ID) - >= index->n_core_fields && n <= index->n_fields)); + >= n_core && n <= index->n_fields)); - if (is_user_rec && leaf && n < index->n_fields) { + if (is_user_rec && n_core && n < index->n_fields) { ut_ad(!index->is_dummy); ut_ad(!dict_index_is_ibuf(index)); n = index->n_fields; @@ -867,7 +875,7 @@ rec_get_offsets_func( } rec_offs_set_n_fields(offsets, n); - rec_init_offsets(rec, index, leaf, offsets); + rec_init_offsets(rec, index, n_core, offsets); return(offsets); } @@ -1764,7 +1772,9 @@ template void rec_convert_dtuple_to_temp( The fields are copied into the memory heap. @param[out] tuple data tuple @param[in] rec index record, or a copy thereof -@param[in] is_leaf whether rec is a leaf page record +@param[in] index index of rec +@param[in] n_core index->n_core_fields at the time rec was + copied, or 0 if non-leaf page record @param[in] n_fields number of fields to copy @param[in,out] heap memory heap */ void @@ -1772,7 +1782,7 @@ rec_copy_prefix_to_dtuple( dtuple_t* tuple, const rec_t* rec, const dict_index_t* index, - bool is_leaf, + ulint n_core, ulint n_fields, mem_heap_t* heap) { @@ -1780,10 +1790,11 @@ rec_copy_prefix_to_dtuple( rec_offs* offsets = offsets_; rec_offs_init(offsets_); - ut_ad(is_leaf || n_fields + ut_ad(n_core <= index->n_core_fields); + ut_ad(n_core || n_fields <= dict_index_get_n_unique_in_tree_nonleaf(index) + 1); - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, n_fields, &heap); ut_ad(rec_validate(rec, offsets)); @@ -2421,7 +2432,8 @@ rec_print( rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_, - page_rec_is_leaf(rec), + page_rec_is_leaf(rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap)); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -2497,7 +2509,8 @@ operator<<(std::ostream& o, const rec_index_print& r) { mem_heap_t* heap = NULL; rec_offs* offsets = rec_get_offsets( - r.m_rec, r.m_index, NULL, page_rec_is_leaf(r.m_rec), + r.m_rec, r.m_index, NULL, page_rec_is_leaf(r.m_rec) + ? r.m_index->n_core_fields : 0, ULINT_UNDEFINED, &heap); rec_print(o, r.m_rec, rec_get_info_bits(r.m_rec, rec_offs_comp(offsets)), @@ -2543,7 +2556,7 @@ rec_get_trx_id( ut_ad(trx_id_col > 0); ut_ad(trx_id_col != ULINT_UNDEFINED); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, trx_id_col + 1, &heap); trx_id = rec_get_nth_field(rec, offsets, trx_id_col, &len); @@ -2594,7 +2607,8 @@ wsrep_rec_get_foreign_key( ut_ad(index_ref); rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index_for, offsets_, true, + offsets = rec_get_offsets(rec, index_for, offsets_, + index_for->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(rec_offs_validate(rec, NULL, offsets)); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 0f9e309accb..d3ca5579d17 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1811,7 +1811,8 @@ PageConverter::update_records( if (deleted || clust_index) { m_offsets = rec_get_offsets( - rec, m_index->m_srv_index, m_offsets, true, + rec, m_index->m_srv_index, m_offsets, + m_index->m_srv_index->n_core_fields, ULINT_UNDEFINED, &m_heap); } @@ -2377,7 +2378,8 @@ row_import_set_sys_max_row_id( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets_, true, ULINT_UNDEFINED, &heap); + rec, index, offsets_, index->n_core_fields, + ULINT_UNDEFINED, &heap); field = rec_get_nth_field( rec, offsets, diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index c17b5cc8d1d..9247c7680bc 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.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 @@ -886,7 +886,7 @@ row_ins_foreign_fill_virtual( rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_); const rec_offs* offsets = - rec_get_offsets(rec, index, offsets_, true, + rec_get_offsets(rec, index, offsets_, index->n_core_fields, ULINT_UNDEFINED, &cascade->heap); TABLE* mysql_table= NULL; upd_t* update = cascade->update; @@ -1640,7 +1640,8 @@ row_ins_check_foreign_constraint( continue; } - offsets = rec_get_offsets(rec, check_index, offsets, true, + offsets = rec_get_offsets(rec, check_index, offsets, + check_index->n_core_fields, ULINT_UNDEFINED, &heap); if (page_rec_is_supremum(rec)) { @@ -2138,7 +2139,8 @@ row_ins_scan_sec_index_for_duplicate( continue; } - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); if (flags & BTR_NO_LOCKING_FLAG) { @@ -2275,7 +2277,8 @@ row_ins_duplicate_error_in_clust_online( ut_ad(!cursor->index->is_instant()); if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) { - *offsets = rec_get_offsets(rec, cursor->index, *offsets, true, + *offsets = rec_get_offsets(rec, cursor->index, *offsets, + cursor->index->n_fields, ULINT_UNDEFINED, heap); err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets); if (err != DB_SUCCESS) { @@ -2286,7 +2289,8 @@ row_ins_duplicate_error_in_clust_online( rec = page_rec_get_next_const(btr_cur_get_rec(cursor)); if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) { - *offsets = rec_get_offsets(rec, cursor->index, *offsets, true, + *offsets = rec_get_offsets(rec, cursor->index, *offsets, + cursor->index->n_fields, ULINT_UNDEFINED, heap); err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets); } @@ -2342,7 +2346,7 @@ row_ins_duplicate_error_in_clust( if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, - true, + cursor->index->n_core_fields, ULINT_UNDEFINED, &heap); /* We set a lock on the possible duplicate: this @@ -2408,7 +2412,7 @@ duplicate: if (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, - true, + cursor->index->n_core_fields, ULINT_UNDEFINED, &heap); if (trx->duplicates) { @@ -2525,7 +2529,7 @@ row_ins_index_entry_big_rec( btr_pcur_open(index, entry, PAGE_CUR_LE, BTR_MODIFY_TREE, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, heap); DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern"); @@ -3084,7 +3088,8 @@ row_ins_sec_index_entry_low( prefix, we must convert the insert into a modify of an existing record */ offsets = rec_get_offsets( - btr_cur_get_rec(&cursor), index, offsets, true, + btr_cur_get_rec(&cursor), index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); err = row_ins_sec_index_entry_by_modify( diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index fb6b1738f74..6095d72bb86 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, 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 @@ -1258,7 +1258,8 @@ row_log_table_get_pk( if (!offsets) { offsets = rec_get_offsets( - rec, index, NULL, true, + rec, index, NULL, + index->n_core_fields, pos + 1, heap); } @@ -1308,7 +1309,8 @@ row_log_table_get_pk( } if (!offsets) { - offsets = rec_get_offsets(rec, index, NULL, true, + offsets = rec_get_offsets(rec, index, NULL, + index->n_core_fields, ULINT_UNDEFINED, heap); } @@ -1980,7 +1982,8 @@ all_done: return(DB_SUCCESS); } - offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL, true, + offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL, + index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(btr_pcur_get_rec(&pcur), offsets)); @@ -2178,7 +2181,7 @@ func_exit_committed: /* Prepare to update (or delete) the record. */ rec_offs* cur_offsets = rec_get_offsets( - btr_pcur_get_rec(&pcur), index, NULL, true, + btr_pcur_get_rec(&pcur), index, NULL, index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); if (!log->same_pk) { diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 2d3ce298f56..f77eae9a76d 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2038,7 +2038,8 @@ end_of_index: rec = page_cur_get_rec(cur); if (online) { - offsets = rec_get_offsets(rec, clust_index, NULL, true, + offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &row_heap); rec_trx_id = row_get_rec_trx_id(rec, clust_index, offsets); @@ -2130,7 +2131,8 @@ end_of_index: duplicate keys. */ continue; } else { - offsets = rec_get_offsets(rec, clust_index, NULL, true, + offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &row_heap); /* This is a locking ALTER TABLE. diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index d79cf29e53c..0b28fe03c41 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -689,6 +689,7 @@ row_mysql_handle_errors( dberr_t err; DBUG_ENTER("row_mysql_handle_errors"); + DEBUG_SYNC_C("row_mysql_handle_errors"); handle_new_error: err = trx->error_state; @@ -1800,12 +1801,11 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) clust_index = dict_table_get_first_index(table); - if (prebuilt->pcur->btr_cur.index == clust_index) { - btr_pcur_copy_stored_position(node->pcur, prebuilt->pcur); - } else { - btr_pcur_copy_stored_position(node->pcur, - prebuilt->clust_pcur); - } + btr_pcur_copy_stored_position(node->pcur, + prebuilt->pcur->btr_cur.index + == clust_index + ? prebuilt->pcur + : prebuilt->clust_pcur); ut_a(node->pcur->rel_pos == BTR_PCUR_ON); @@ -2023,7 +2023,8 @@ row_unlock_for_mysql( rec_offs* offsets = offsets_; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); rec_trx_id = row_get_rec_trx_id(rec, index, offsets); @@ -4795,7 +4796,7 @@ func_exit: rec = buf + mach_read_from_4(buf); - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, index->n_core_fields, ULINT_UNDEFINED, &heap); if (prev_entry != NULL) { diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 19e981ee30f..6a7f5921aa3 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, 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 @@ -127,8 +127,8 @@ row_purge_remove_clust_if_poss_low( rec = btr_pcur_get_rec(&node->pcur); - offsets = rec_get_offsets( - rec, index, offsets_, true, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets_, index->n_core_fields, + ULINT_UNDEFINED, &heap); if (node->roll_ptr != row_get_rec_roll_ptr(rec, index, offsets)) { /* Someone else has modified the record later: do not remove */ @@ -803,7 +803,8 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr) rec_offs offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2]; rec_offs_init(offsets_); rec_offs* offsets = rec_get_offsets( - rec, index, offsets_, true, trx_id_pos + 2, &heap); + rec, index, offsets_, index->n_core_fields, + trx_id_pos + 2, &heap); ut_ad(heap == NULL); ut_ad(dict_index_get_nth_field(index, trx_id_pos) @@ -1360,7 +1361,7 @@ purge_node_t::validate_pcur() dict_index_t* clust_index = pcur.btr_cur.index; rec_offs* offsets = rec_get_offsets( - pcur.old_rec, clust_index, NULL, true, + pcur.old_rec, clust_index, NULL, pcur.old_n_core_fields, pcur.old_n_fields, &heap); /* Here we are comparing the purge ref record and the stored initial diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index f6b7a9f49b6..6f34c9fcc9b 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 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 @@ -422,7 +422,8 @@ row_build_low( ut_ad(!col_map || col_table); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); @@ -836,7 +837,7 @@ row_build_row_ref( ut_ad(heap != NULL); ut_ad(!dict_index_is_clust(index)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); /* Secondary indexes must not contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); @@ -945,7 +946,8 @@ row_build_row_ref_in_tuple( ut_ad(clust_index); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 979aea2f953..248a6592913 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -200,9 +200,11 @@ row_sel_sec_rec_is_for_clust_rec( ib_vcol_row vc(heap); clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs, - true, ULINT_UNDEFINED, &heap); + sec_index->n_fields, + ULINT_UNDEFINED, &heap); n = dict_index_get_n_ordering_defined_by_user(sec_index); @@ -906,7 +908,9 @@ row_sel_get_clust_rec( offsets = rec_get_offsets(rec, btr_pcur_get_btr_cur(&plan->pcur)->index, - offsets, true, ULINT_UNDEFINED, &heap); + offsets, + btr_pcur_get_btr_cur(&plan->pcur)->index + ->n_core_fields, ULINT_UNDEFINED, &heap); row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets); @@ -941,7 +945,8 @@ row_sel_get_clust_rec( goto err_exit; } - offsets = rec_get_offsets(clust_rec, index, offsets, true, + offsets = rec_get_offsets(clust_rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); if (!node->read_view) { @@ -1161,7 +1166,8 @@ re_scan: rec = btr_pcur_get_rec(pcur); my_offsets = offsets_; - my_offsets = rec_get_offsets(rec, index, my_offsets, true, + my_offsets = rec_get_offsets(rec, index, my_offsets, + index->n_fields, ULINT_UNDEFINED, &heap); /* No match record */ @@ -1184,7 +1190,7 @@ re_scan: rtr_rec_t* rtr_rec = &(*it); my_offsets = rec_get_offsets( - rtr_rec->r_rec, index, my_offsets, true, + rtr_rec->r_rec, index, my_offsets, index->n_fields, ULINT_UNDEFINED, &heap); err = lock_sec_rec_read_check_and_lock( @@ -1493,7 +1499,7 @@ exhausted: rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_index_is_clust(index)) { @@ -1709,7 +1715,7 @@ rec_loop: trx = thr_get_trx(thr); offsets = rec_get_offsets(next_rec, index, offsets, - true, + index->n_core_fields, ULINT_UNDEFINED, &heap); /* If innodb_locks_unsafe_for_binlog option is used @@ -1774,7 +1780,8 @@ skip_lock: ulint lock_type; trx_t* trx; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); trx = thr_get_trx(thr); @@ -1861,7 +1868,7 @@ skip_lock: /* PHASE 3: Get previous version in a consistent read */ cons_read_requires_clust_rec = FALSE; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); if (consistent_read) { @@ -1892,7 +1899,8 @@ skip_lock: exhausted. */ offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); /* Fetch the columns needed in @@ -3217,7 +3225,8 @@ class Row_sel_get_clust_rec_for_mysql ut_ad(rec_offs_validate(cached_clust_rec, index, offsets)); ut_ad(index->first_user_field() <= rec_offs_n_fields(offsets)); - ut_ad(vers_offs == rec_get_offsets(cached_old_vers, index, vers_offs, true, + ut_ad(vers_offs == rec_get_offsets(cached_old_vers, index, vers_offs, + index->n_core_fields, index->db_trx_id(), &heap)); ut_ad(!heap); for (unsigned n= index->db_trx_id(); n--; ) @@ -3404,7 +3413,8 @@ Row_sel_get_clust_rec_for_mysql::operator()( goto func_exit; } - *offsets = rec_get_offsets(clust_rec, clust_index, *offsets, true, + *offsets = rec_get_offsets(clust_rec, clust_index, *offsets, + clust_index->n_core_fields, ULINT_UNDEFINED, offset_heap); if (prebuilt->select_lock_type != LOCK_NONE) { @@ -3478,7 +3488,8 @@ Row_sel_get_clust_rec_for_mysql::operator()( ut_d(check_eq(clust_index, *offsets)); *offsets = rec_get_offsets( old_vers, clust_index, *offsets, - true, ULINT_UNDEFINED, offset_heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, offset_heap); } } @@ -3901,7 +3912,7 @@ exhausted: /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ - *offsets = rec_get_offsets(rec, index, *offsets, true, + *offsets = rec_get_offsets(rec, index, *offsets, index->n_core_fields, ULINT_UNDEFINED, heap); if (!lock_clust_rec_cons_read_sees(rec, index, *offsets, @@ -4035,7 +4046,7 @@ row_sel_fill_vrow( ut_ad(!index->is_instant()); ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); *vrow = dtuple_create_with_vcol( @@ -4678,7 +4689,7 @@ wait_table_again: const rec_t* next_rec = page_rec_get_next_const(rec); offsets = rec_get_offsets(next_rec, index, offsets, - true, + index->n_core_fields, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(pcur, next_rec, index, offsets, @@ -4762,7 +4773,8 @@ rec_loop: level we do not lock gaps. Supremum record is really a gap and therefore we do not set locks there. */ - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(pcur, rec, index, offsets, @@ -4865,7 +4877,7 @@ wrong_offs: ut_ad(fil_page_index_page_check(btr_pcur_get_page(pcur))); ut_ad(btr_page_get_index_id(btr_pcur_get_page(pcur)) == index->id); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(srv_force_recovery > 0)) { @@ -5128,7 +5140,8 @@ no_gap_lock: Do a normal locking read. */ offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); goto locks_ok; case DB_DEADLOCK: @@ -5502,7 +5515,7 @@ use_covering_index: /* We used 'offsets' for the clust rec, recalculate them for 'rec' */ offsets = rec_get_offsets(rec, index, offsets, - true, + index->n_core_fields, ULINT_UNDEFINED, &heap); result_rec = rec; @@ -5955,7 +5968,7 @@ row_search_autoinc_read_column( rec_offs_init(offsets_); ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, col_no + 1, &heap); if (rec_offs_nth_sql_null(offsets, col_no)) { diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index f72ad28e70e..756d6d54024 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, 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 @@ -117,7 +117,8 @@ row_undo_ins_remove_clust_rec( const rec_t* rec = btr_cur_get_rec(btr_cur); mem_heap_t* heap = NULL; const rec_offs* offsets = rec_get_offsets( - rec, index, NULL, true, ULINT_UNDEFINED, &heap); + rec, index, NULL, index->n_core_fields, + ULINT_UNDEFINED, &heap); row_log_table_delete(rec, index, offsets, NULL); mem_heap_free(heap); } diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 288173a91c2..c7c19eaadb2 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, 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 @@ -163,8 +163,9 @@ static ulint row_trx_id_offset(const rec_t* rec, const dict_index_t* index) rec_offs_init(offsets_); mem_heap_t* heap = NULL; const ulint trx_id_pos = index->n_uniq ? index->n_uniq : 1; - rec_offs* offsets = rec_get_offsets(rec, index, offsets_, true, - trx_id_pos + 1, &heap); + rec_offs* offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, + trx_id_pos + 1, &heap); ut_ad(!heap); ulint len; trx_id_offset = rec_get_nth_field_offs( @@ -409,7 +410,8 @@ row_undo_mod_clust( rec_offs offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2]; rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets_, true, trx_id_pos + 2, &heap); + rec, index, offsets_, index->n_core_fields, + trx_id_pos + 2, &heap); ulint len; ulint trx_id_offset = rec_get_nth_field_offs( offsets, trx_id_pos, &len); @@ -794,7 +796,8 @@ try_again: offsets_heap = NULL; offsets = rec_get_offsets( btr_cur_get_rec(btr_cur), - index, NULL, true, ULINT_UNDEFINED, &offsets_heap); + index, NULL, index->n_core_fields, ULINT_UNDEFINED, + &offsets_heap); update = row_upd_build_sec_rec_difference_binary( btr_cur_get_rec(btr_cur), index, offsets, entry, heap); if (upd_get_n_fields(update) == 0) { diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 762228503be..a8c35186a7d 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 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 @@ -187,7 +187,8 @@ row_undo_search_clust_to_pcur( rec = btr_pcur_get_rec(&node->pcur); - offsets = rec_get_offsets(rec, clust_index, offsets, true, + offsets = rec_get_offsets(rec, clust_index, offsets, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); found = row_get_rec_roll_ptr(rec, clust_index, offsets) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 97640debc03..c85caa30fe6 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1067,7 +1067,8 @@ row_upd_build_difference_binary( == trx_id_pos + 1); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); @@ -2218,7 +2219,8 @@ row_upd_store_row( rec = btr_pcur_get_rec(node->pcur); - offsets = rec_get_offsets(rec, clust_index, offsets_, true, + offsets = rec_get_offsets(rec, clust_index, offsets_, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_table_has_atomic_blobs(node->table)) { @@ -2451,7 +2453,7 @@ row_upd_sec_index_entry( && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { rec_offs* offsets = rec_get_offsets( - rec, index, NULL, true, + rec, index, NULL, index->n_core_fields, ULINT_UNDEFINED, &heap); err = wsrep_row_upd_check_foreign_constraints( @@ -2494,12 +2496,9 @@ row_upd_sec_index_entry( ut_ad(err == DB_SUCCESS); if (referenced) { - - rec_offs* offsets; - - offsets = rec_get_offsets( - rec, index, NULL, true, ULINT_UNDEFINED, - &heap); + rec_offs* offsets = rec_get_offsets( + rec, index, NULL, index->n_core_fields, + ULINT_UNDEFINED, &heap); /* NOTE that the following call loses the position of pcur ! */ @@ -2741,7 +2740,8 @@ row_upd_clust_rec_by_insert( we update the primary key. Delete-mark the old record in the clustered index and prepare to insert a new entry. */ rec = btr_cur_get_rec(btr_cur); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(page_rec_is_user_rec(rec)); @@ -3152,7 +3152,7 @@ row_upd_clust_step( } rec = btr_pcur_get_rec(pcur); - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, index->n_core_fields, ULINT_UNDEFINED, &heap); if (!flags && !node->has_clust_rec_x_lock) { diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index aa2400a91ad..cde4e9e7b89 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, 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 @@ -116,7 +116,8 @@ row_vers_impl_x_locked_low( heap = mem_heap_create(1024); clust_offsets = rec_get_offsets(clust_rec, clust_index, clust_offsets_, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets); if (trx_id == 0) { @@ -239,7 +240,8 @@ not_locked: } clust_offsets = rec_get_offsets( - prev_version, clust_index, clust_offsets_, true, + prev_version, clust_index, clust_offsets_, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); vers_del = rec_get_deleted_flag(prev_version, comp); @@ -569,7 +571,8 @@ row_vers_build_cur_vrow_low( clust_offsets = rec_get_offsets(prev_version, clust_index, NULL, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); ulint entry_len = dict_index_get_n_fields(index); @@ -711,7 +714,8 @@ row_vers_vc_matches_cluster( clust_offsets = rec_get_offsets(prev_version, clust_index, NULL, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); ulint entry_len = dict_index_get_n_fields(index); @@ -849,7 +853,8 @@ row_vers_build_cur_vrow( index, roll_ptr, trx_id, v_heap, &cur_vrow, mtr); } - *clust_offsets = rec_get_offsets(rec, clust_index, NULL, true, + *clust_offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); return(cur_vrow); } @@ -906,7 +911,8 @@ row_vers_old_has_index_entry( comp = page_rec_is_comp(rec); ut_ad(!dict_table_is_comp(index->table) == !comp); heap = mem_heap_create(1024); - clust_offsets = rec_get_offsets(rec, clust_index, NULL, true, + clust_offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_index_has_virtual(index)) { @@ -995,7 +1001,8 @@ row_vers_old_has_index_entry( } } clust_offsets = rec_get_offsets(rec, clust_index, NULL, - true, + clust_index + ->n_core_fields, ULINT_UNDEFINED, &heap); } else { @@ -1074,7 +1081,8 @@ unsafe_to_purge: } clust_offsets = rec_get_offsets(prev_version, clust_index, - NULL, true, + NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_index_has_virtual(index)) { @@ -1215,7 +1223,7 @@ row_vers_build_for_consistent_read( *offsets = rec_get_offsets( prev_version, index, *offsets, - true, ULINT_UNDEFINED, offset_heap); + index->n_core_fields, ULINT_UNDEFINED, offset_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(prev_version, *offsets)); @@ -1331,11 +1339,10 @@ committed_version_trx: semi-consistent read. */ version = rec; - *offsets = rec_get_offsets(version, - index, *offsets, - true, - ULINT_UNDEFINED, - offset_heap); + *offsets = rec_get_offsets( + version, index, *offsets, + index->n_core_fields, ULINT_UNDEFINED, + offset_heap); } buf = static_cast( @@ -1378,7 +1385,8 @@ committed_version_trx: } version = prev_version; - *offsets = rec_get_offsets(version, index, *offsets, true, + *offsets = rec_get_offsets(version, index, *offsets, + index->n_core_fields, ULINT_UNDEFINED, offset_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(version, *offsets)); diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 71872ce45b2..59e0bed8006 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -713,7 +713,8 @@ fill_lock_data( ut_a(n_fields > 0); heap = NULL; - offsets = rec_get_offsets(rec, index, offsets, true, n_fields, &heap); + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, + n_fields, &heap); /* format and store the data */ diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 09e6ad79685..9c7106facaf 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2019, 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 @@ -2412,7 +2412,8 @@ trx_undo_prev_version_build( rec_offs offsets_dbg[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_dbg); ut_a(!rec_offs_any_null_extern( - *old_vers, rec_get_offsets(*old_vers, index, offsets_dbg, true, + *old_vers, rec_get_offsets(*old_vers, index, offsets_dbg, + index->n_core_fields, ULINT_UNDEFINED, &heap))); #endif // defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index d331beb9230..7f7be193175 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2017, 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 @@ -667,7 +667,7 @@ const char * dbug_print_rec(const rec_t* rec, dict_index_t* index) rec_offs* offsets = offsets_; rec_offs_init(offsets_); mem_heap_t* tmp_heap = NULL; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); rec_printer r(rec, offsets); strmake(dbug_print_buf, r.str().c_str(), sizeof(dbug_print_buf) - 1); From 55a7682a30963c1ee5e367d9f3b9b2e50e12d663 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 13 Apr 2021 16:44:09 +0200 Subject: [PATCH 34/35] -DMYSQL_MAINTAINER_MODE=NO also add =WARN as an alias for =OFF and clarify the help text --- CMakeLists.txt | 2 +- cmake/maintainer.cmake | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80f87af2cb5..36662113108 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,7 +134,7 @@ IF(DEFINED ENV{CPPFLAGS}) ADD_DEFINITIONS($ENV{CPPFLAGS}) ENDIF() -SET(MYSQL_MAINTAINER_MODE "AUTO" CACHE STRING "MySQL maintainer-specific development environment. Options are: ON OFF AUTO.") +SET(MYSQL_MAINTAINER_MODE "AUTO" CACHE STRING "Enable MariaDB maintainer-specific warnings. One of: NO (warnings are disabled) WARN (warnings are enabled) ERR (warnings are errors) AUTO (warnings are errors in Debug only)") # Packaging IF (NOT CPACK_GENERATOR) diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake index 9c51cb797bb..933b04fb7f0 100644 --- a/cmake/maintainer.cmake +++ b/cmake/maintainer.cmake @@ -1,5 +1,5 @@ # Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2020, MariaDB +# Copyright (c) 2011, 2021, MariaDB # # 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 @@ -14,6 +14,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +IF(MYSQL_MAINTAINER_MODE STREQUAL "NO") + RETURN() +ENDIF() + # Common warning flags for GCC, G++, Clang and Clang++ SET(MY_WARNING_FLAGS -Wall @@ -41,7 +45,7 @@ IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "6.0.0") SET(MY_ERROR_FLAGS ${MY_ERROR_FLAGS} -Wno-error=maybe-uninitialized) ENDIF() -IF(MYSQL_MAINTAINER_MODE MATCHES "OFF") +IF(MYSQL_MAINTAINER_MODE MATCHES "OFF|WARN") RETURN() ELSEIF(MYSQL_MAINTAINER_MODE MATCHES "AUTO") SET(WHERE DEBUG) From 13d0641710802bd57b0c0d88c9fc321932014994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 14 Apr 2021 10:09:04 +0300 Subject: [PATCH 35/35] Fixup merge 6e6318b29b446f76f01f2ef65d1460870b607d2a --- sql/sql_select.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f5d05794e11..b4e6c505261 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB Corporation. + Copyright (c) 2009, 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 @@ -12854,7 +12854,7 @@ bool JOIN_TAB::preread_init() derived->get_unit()->uncacheable) && mysql_handle_single_derived(join->thd->lex, derived, DT_CREATE | DT_FILL)) - DBUG_RETURN(TRUE); + DBUG_RETURN(TRUE); if (!(derived->get_unit()->uncacheable & UNCACHEABLE_DEPENDENT) || derived->is_nonrecursive_derived_with_rec_ref()) @@ -12872,7 +12872,7 @@ bool JOIN_TAB::preread_init() /* init ftfuns for just initialized derived table */ if (table->fulltext_searched) if (init_ftfuncs(join->thd, join->select_lex, MY_TEST(join->order))) - return TRUE; + DBUG_RETURN(TRUE); DBUG_RETURN(FALSE); }