From dc82f70e9f203fb6cd2e9dd2b43beb1a2d6e791e Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 13 Sep 2017 15:17:28 +0400 Subject: [PATCH 1/9] MDEV-13633 JSON_ARRAY() - bad output with some UTF8 characters. set_charset() calls added for Item_func_json_arran and Item_func_json_object::val_str-s. --- mysql-test/r/func_json.result | 6 ++++++ mysql-test/t/func_json.test | 6 ++++++ sql/item_jsonfunc.cc | 2 ++ 3 files changed, 14 insertions(+) diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 0c60c42ec77..5c3134b7ce9 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -699,3 +699,9 @@ select @str, @path, JSON_EXTRACT(@str, @path); select json_array(5,json_query('[1,2]','$')); json_array(5,json_query('[1,2]','$')) [5, [1,2]] +SELECT JSON_ARRAY('1. ě 2. š 3. č 4. ř 5. ž 6. ý 7. á 8. í 9. é 10. ů 11. ú') AS json_data; +json_data +["1. ě 2. š 3. č 4. ř 5. ž 6. ý 7. á 8. í 9. é 10. ů 11. ú"] +SELECT JSON_OBJECT("user","Jožko Mrkvičká") as json_data; +json_data +{"user": "Jožko Mrkvičká"} diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 39e31b8bb58..c660cb14856 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -354,3 +354,9 @@ select @str, @path, JSON_EXTRACT(@str, @path); # select json_array(5,json_query('[1,2]','$')); +# +# MDEV-13633 JSON_ARRAY() - bad output with some UTF8 characters. +# + +SELECT JSON_ARRAY('1. ě 2. š 3. č 4. ř 5. ž 6. ý 7. á 8. í 9. é 10. ů 11. ú') AS json_data; +SELECT JSON_OBJECT("user","Jožko Mrkvičká") as json_data; diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index a39b5f3f263..6398929defc 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1473,6 +1473,7 @@ String *Item_func_json_array::val_str(String *str) uint n_arg; str->length(0); + str->set_charset(collation.collation); if (str->append("[", 1) || ((arg_count > 0) && append_json_value(str, args[0], &tmp_val))) @@ -1797,6 +1798,7 @@ String *Item_func_json_object::val_str(String *str) uint n_arg; str->length(0); + str->set_charset(collation.collation); if (str->append("{", 1) || (arg_count > 0 && From 250ca1c1d2925eb38dbec5c44430af9b87b2ad92 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 13 Sep 2017 16:45:42 +0400 Subject: [PATCH 2/9] MDEV-13707 Server in ORACLE mode crashes on ALTER with wrong DEFAULT clause --- mysql-test/r/default.result | 7 +++++++ mysql-test/t/default.test | 10 ++++++++++ sql/item.cc | 4 ++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index 2780ed3b168..8fa88066f7c 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -3381,4 +3381,11 @@ create table t1 (col1 int default(-(default(col1)))); ERROR 01000: Expression for field `col1` is refering to uninitialized field `col1` create table t1 (col int default (yearweek((exp(710))))); ERROR 22003: DOUBLE value is out of range in 'exp(710)' +# +# MDEV-13707 Server in ORACLE mode crashes on ALTER with wrong DEFAULT clause +# +CREATE OR REPLACE TABLE t1(i int); +ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; +ERROR 42S22: Unknown column 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 'DEFAULT' +DROP TABLE t1; # end of 10.2 test diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index 84ef620de04..bfea214f548 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -2095,4 +2095,14 @@ create table t1 (col1 int default(-(default(col1)))); --error ER_DATA_OUT_OF_RANGE create table t1 (col int default (yearweek((exp(710))))); +--echo # +--echo # MDEV-13707 Server in ORACLE mode crashes on ALTER with wrong DEFAULT clause +--echo # + +CREATE OR REPLACE TABLE t1(i int); +--error ER_BAD_FIELD_ERROR +ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; +DROP TABLE t1; + + --echo # end of 10.2 test diff --git a/sql/item.cc b/sql/item.cc index c36be16425f..6db1b355ed3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1446,9 +1446,9 @@ static inline void mark_unsupported_func(const char *where, const char *processor_name) { char buff[64]; - sprintf(buff, "%s::%s", where ? where: "", processor_name); + my_snprintf(buff, sizeof(buff), "%s::%s", where ? where: "", processor_name); DBUG_ENTER(buff); - sprintf(buff, "%s returns TRUE: unsupported function", processor_name); + my_snprintf(buff, sizeof(buff), "%s returns TRUE: unsupported function", processor_name); DBUG_PRINT("info", ("%s", buff)); DBUG_VOID_RETURN; } From dd35fb35fa03c034ff66fcb25bdabf2bc3e1a097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Sep 2017 09:27:15 +0300 Subject: [PATCH 3/9] Return uint16_t instead of ulint --- storage/innobase/buf/buf0lru.cc | 5 ++--- storage/innobase/include/fil0fil.h | 5 ++--- storage/innobase/include/page0page.h | 4 ++-- storage/innobase/include/page0page.ic | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 1e7b7065b12..2137760e815 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -2697,14 +2697,13 @@ buf_LRU_print_instance( const byte* frame; case BUF_BLOCK_FILE_PAGE: frame = buf_block_get_frame((buf_block_t*) bpage); - fprintf(stderr, "\ntype " ULINTPF - " index id " IB_ID_FMT "\n", + fprintf(stderr, "\ntype %u index id " IB_ID_FMT "\n", fil_page_get_type(frame), btr_page_get_index_id(frame)); break; case BUF_BLOCK_ZIP_PAGE: frame = bpage->zip.data; - fprintf(stderr, "\ntype " ULINTPF " size " ULINTPF + fprintf(stderr, "\ntype %u size " ULINTPF " index id " IB_ID_FMT "\n", fil_page_get_type(frame), bpage->size.physical(), diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 3b53fa28be3..d3336c5f5b5 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1321,9 +1321,8 @@ fil_page_reset_type( @param[in] page file page @return page type */ inline -ulint -fil_page_get_type( - const byte* page) +uint16_t +fil_page_get_type(const byte* page) { return(mach_read_from_2(page + FIL_PAGE_TYPE)); } diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 0aca13ac159..9243bcaa717 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2017, 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 @@ -264,7 +264,7 @@ page_set_ssn_id( /*************************************************************//** Reads the given header field. */ UNIV_INLINE -ulint +uint16_t page_header_get_field( /*==================*/ const page_t* page, /*!< in: page */ diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 2ad5f26dcc1..b464e497de1 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -170,7 +170,7 @@ page_set_ssn_id( /*************************************************************//** Reads the given header field. */ UNIV_INLINE -ulint +uint16_t page_header_get_field( /*==================*/ const page_t* page, /*!< in: page */ From d06e4fc6a36a5ef9e8c37c29acb143970f136f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Sep 2017 09:31:13 +0300 Subject: [PATCH 4/9] Do not require a debug non-embedded server in the test This also avoids hitting the hang at server shutdown. That hang should be fixed, of course. --- mysql-test/suite/gcol/r/gcol_update.result | 30 +++++++++++----- mysql-test/suite/gcol/t/gcol_update.test | 41 ++++++++++++++-------- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/gcol/r/gcol_update.result b/mysql-test/suite/gcol/r/gcol_update.result index 380d1c1efef..720ff533bac 100644 --- a/mysql-test/suite/gcol/r/gcol_update.result +++ b/mysql-test/suite/gcol/r/gcol_update.result @@ -1,13 +1,19 @@ -set global innodb_purge_stop_now = 1; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; create table t1(f1 int not null, f2 blob not null, f3 blob not null, vchar char(2) as (substr(f3,2,2)) virtual, primary key(f1, f3(5)), index(vchar))engine=innodb; insert into t1(f1,f2,f3) values(1, repeat('a',8000), repeat('b', 9000)); update t1 set f1=5 where f1=1; delete from t1 where f1=5; -set global innodb_purge_run_now=1; -set global innodb_fast_shutdown=0; -set global innodb_purge_stop_now = 1; +connection purge_control; +COMMIT; +InnoDB 0 transactions not purged +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; drop table t1; create table t1(f1 int not null, f2 blob not null, f3 blob not null, vchar char(2) as (substr(f3,2,2)) virtual, @@ -15,9 +21,11 @@ primary key(f1, f3(5)), index(vchar, f3(2)))engine=innodb; insert into t1(f1,f2,f3) values(1, repeat('a',8000), repeat('b', 9000)); update t1 set f1=5 where f1=1; delete from t1 where f1=5; -set global innodb_purge_run_now=1; -set global innodb_fast_shutdown=0; -set global innodb_purge_stop_now = 1; +connection purge_control; +COMMIT; +InnoDB 0 transactions not purged +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; drop table t1; create table t1(f1 int not null, f2 blob not null, f3 blob not null, vchar blob as (f3) virtual, @@ -25,6 +33,10 @@ primary key(f1, f3(5)), index(vchar(3)))engine=innodb; insert into t1(f1,f2,f3) values(1, repeat('a',8000), repeat('b', 9000)); update t1 set f1=5 where f1=1; delete from t1 where f1=5; -set global innodb_purge_run_now=1; -set global innodb_fast_shutdown=0; +connection purge_control; +COMMIT; +InnoDB 0 transactions not purged +disconnect purge_control; +connection default; drop table t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/gcol_update.test b/mysql-test/suite/gcol/t/gcol_update.test index 0a7265bebac..8652ce7a638 100644 --- a/mysql-test/suite/gcol/t/gcol_update.test +++ b/mysql-test/suite/gcol/t/gcol_update.test @@ -1,9 +1,12 @@ ---source include/have_debug.inc --source include/have_innodb.inc -# The embedded server does not support restarting. ---source include/not_embedded.inc -set global innodb_purge_stop_now = 1; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; + +connect (purge_control,localhost,root); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; # Index on virtual column @@ -16,10 +19,12 @@ insert into t1(f1,f2,f3) values(1, repeat('a',8000), repeat('b', 9000)); update t1 set f1=5 where f1=1; delete from t1 where f1=5; -set global innodb_purge_run_now=1; -set global innodb_fast_shutdown=0; ---source include/restart_mysqld.inc -set global innodb_purge_stop_now = 1; +connection purge_control; +COMMIT; +--source ../../innodb/include/wait_all_purged.inc +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; + drop table t1; # Index on virtual column and blob @@ -33,10 +38,11 @@ insert into t1(f1,f2,f3) values(1, repeat('a',8000), repeat('b', 9000)); update t1 set f1=5 where f1=1; delete from t1 where f1=5; -set global innodb_purge_run_now=1; -set global innodb_fast_shutdown=0; ---source include/restart_mysqld.inc -set global innodb_purge_stop_now = 1; +connection purge_control; +COMMIT; +--source ../../innodb/include/wait_all_purged.inc +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; drop table t1; # Index on virtual column of blob type @@ -50,7 +56,12 @@ insert into t1(f1,f2,f3) values(1, repeat('a',8000), repeat('b', 9000)); update t1 set f1=5 where f1=1; delete from t1 where f1=5; -set global innodb_purge_run_now=1; -set global innodb_fast_shutdown=0; ---source include/restart_mysqld.inc +connection purge_control; +COMMIT; +--source ../../innodb/include/wait_all_purged.inc +disconnect purge_control; + +connection default; drop table t1; + +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; From 24062fed7026cd9a65864402a6a4761ef88ade39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Sep 2017 11:04:49 +0300 Subject: [PATCH 5/9] Remove the debug variables innodb_purge_stop_now, innodb_purge_run_now The InnoDB purge subsystem can be best stopped by opening a read view, for example by START TRANSACTION WITH CONSISTENT SNAPSHOT. To ensure that everything is purged, use wait_all_purged.inc, which waits for the History list length in SHOW ENGINE INNODB STATUS to reach 0. Setting innodb_purge_run_now never guaranteed this. --- .../suite/innodb/r/innodb-wl5522-debug.result | 9 ++- .../suite/innodb/t/innodb-wl5522-debug.test | 9 ++- .../innodb_zip/r/wl5522_debug_zip.result | 9 ++- .../suite/innodb_zip/t/wl5522_debug_zip.test | 9 ++- .../r/innodb_purge_run_now_basic.result | 27 --------- .../r/innodb_purge_stop_now_basic.result | 27 --------- .../suite/sys_vars/r/sysvars_innodb.result | 28 --------- .../t/innodb_purge_run_now_basic.test | 53 ---------------- .../t/innodb_purge_stop_now_basic.test | 53 ---------------- storage/innobase/handler/ha_innodb.cc | 60 ------------------- 10 files changed, 28 insertions(+), 256 deletions(-) delete mode 100644 mysql-test/suite/sys_vars/r/innodb_purge_run_now_basic.result delete mode 100644 mysql-test/suite/sys_vars/r/innodb_purge_stop_now_basic.result delete mode 100644 mysql-test/suite/sys_vars/t/innodb_purge_run_now_basic.test delete mode 100644 mysql-test/suite/sys_vars/t/innodb_purge_stop_now_basic.test diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result index 4d748d6ebed..99e9c49eee9 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result @@ -494,7 +494,9 @@ c4 VARCHAR(2048), INDEX idx1(c2), INDEX idx2(c3(512)), INDEX idx3(c4(512))) Engine=InnoDB; -SET GLOBAL INNODB_PURGE_STOP_NOW=ON; +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; SET GLOBAL innodb_disable_background_merge=ON; SET GLOBAL innodb_monitor_reset = ibuf_merges; SET GLOBAL innodb_monitor_reset = ibuf_merges_insert; @@ -659,7 +661,10 @@ FROM information_schema.innodb_metrics WHERE name = 'ibuf_merges_inserts' AND count > 0; name SET GLOBAL innodb_disable_background_merge=OFF; -SET GLOBAL INNODB_PURGE_RUN_NOW=ON; +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; DROP TABLE test_wl5522.t1; CREATE TABLE test_wl5522.t1 ( c1 BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test index 6b6506e8481..ca37521b9cf 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test @@ -1055,7 +1055,9 @@ CREATE TABLE test_wl5522.t1 ( INDEX idx3(c4(512))) Engine=InnoDB; # Stop purge so that it doesn't remove the delete marked entries. -SET GLOBAL INNODB_PURGE_STOP_NOW=ON; +connect (purge_control,localhost,root); +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; # Disable change buffer merge from the master thread, additionally # enable aggressive flushing so that more changes are buffered. @@ -1125,7 +1127,10 @@ SELECT name SET GLOBAL innodb_disable_background_merge=OFF; # Enable normal operation -SET GLOBAL INNODB_PURGE_RUN_NOW=ON; +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; DROP TABLE test_wl5522.t1; diff --git a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result index d20cc452612..394a2ea1f09 100644 --- a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result +++ b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result @@ -123,7 +123,9 @@ INDEX idx1(c2), INDEX idx2(c3(512)), INDEX idx3(c4(512))) Engine=InnoDB ROW_FORMAT=COMPRESSED; -SET GLOBAL INNODB_PURGE_STOP_NOW=ON; +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; SET GLOBAL innodb_disable_background_merge=ON; SET GLOBAL innodb_monitor_reset = ibuf_merges; SET GLOBAL innodb_monitor_reset = ibuf_merges_insert; @@ -288,7 +290,10 @@ FROM information_schema.innodb_metrics WHERE name = 'ibuf_merges_inserts' AND count > 0; name SET GLOBAL innodb_disable_background_merge=OFF; -SET GLOBAL INNODB_PURGE_RUN_NOW=ON; +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; DROP TABLE test_wl5522.t1; CREATE TABLE test_wl5522.t1 ( c1 BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, diff --git a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test index 0898a32fbf5..986c0508891 100644 --- a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test +++ b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test @@ -321,7 +321,9 @@ CREATE TABLE test_wl5522.t1 ( ROW_FORMAT=COMPRESSED; # Stop purge so that it doesn't remove the delete marked entries. -SET GLOBAL INNODB_PURGE_STOP_NOW=ON; +connect (purge_control,localhost,root); +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; # Disable change buffer merge from the master thread, additionally # enable aggressive flushing so that more changes are buffered. @@ -391,7 +393,10 @@ SELECT name SET GLOBAL innodb_disable_background_merge=OFF; # Enable normal operation -SET GLOBAL INNODB_PURGE_RUN_NOW=ON; +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; DROP TABLE test_wl5522.t1; diff --git a/mysql-test/suite/sys_vars/r/innodb_purge_run_now_basic.result b/mysql-test/suite/sys_vars/r/innodb_purge_run_now_basic.result deleted file mode 100644 index 41204422767..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_purge_run_now_basic.result +++ /dev/null @@ -1,27 +0,0 @@ -SELECT name, count -FROM information_schema.innodb_metrics -WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; -name count -purge_stop_count 0 -purge_resume_count 0 -SET @orig = @@global.innodb_purge_run_now; -SELECT @orig; -@orig -0 -SET GLOBAL innodb_purge_stop_now = ON; -SELECT name, count -FROM information_schema.innodb_metrics -WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; -name count -purge_stop_count 1 -purge_resume_count 0 -SET GLOBAL innodb_purge_run_now = ON; -SELECT @@global.innodb_purge_run_now; -@@global.innodb_purge_run_now -0 -SELECT name, count -FROM information_schema.innodb_metrics -WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; -name count -purge_stop_count 1 -purge_resume_count 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_purge_stop_now_basic.result b/mysql-test/suite/sys_vars/r/innodb_purge_stop_now_basic.result deleted file mode 100644 index 41204422767..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_purge_stop_now_basic.result +++ /dev/null @@ -1,27 +0,0 @@ -SELECT name, count -FROM information_schema.innodb_metrics -WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; -name count -purge_stop_count 0 -purge_resume_count 0 -SET @orig = @@global.innodb_purge_run_now; -SELECT @orig; -@orig -0 -SET GLOBAL innodb_purge_stop_now = ON; -SELECT name, count -FROM information_schema.innodb_metrics -WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; -name count -purge_stop_count 1 -purge_resume_count 0 -SET GLOBAL innodb_purge_run_now = ON; -SELECT @@global.innodb_purge_run_now; -@@global.innodb_purge_run_now -0 -SELECT name, count -FROM information_schema.innodb_metrics -WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; -name count -purge_stop_count 1 -purge_resume_count 1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index b2c8ada4b27..548142ef523 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2274,34 +2274,6 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME INNODB_PURGE_RUN_NOW -SESSION_VALUE NULL -GLOBAL_VALUE OFF -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE OFF -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Set purge state to RUN -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME INNODB_PURGE_STOP_NOW -SESSION_VALUE NULL -GLOBAL_VALUE OFF -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE OFF -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Set purge state to STOP -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_PURGE_THREADS SESSION_VALUE NULL GLOBAL_VALUE 4 diff --git a/mysql-test/suite/sys_vars/t/innodb_purge_run_now_basic.test b/mysql-test/suite/sys_vars/t/innodb_purge_run_now_basic.test deleted file mode 100644 index 0704784dbcc..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_purge_run_now_basic.test +++ /dev/null @@ -1,53 +0,0 @@ -# -# Basic test for innodb_purge_run_now, note it is a duplicate of -# innodb_purge_stop_now. -# - --- source include/have_innodb.inc - -# The config variable is a debug variable for now --- source include/have_debug.inc - ---disable_query_log -# Enable metrics for the counters we are going to use -set global innodb_monitor_enable = purge_stop_count; -set global innodb_monitor_enable = purge_resume_count; ---enable_query_log - -# Should be 0 for both -SELECT name, count - FROM information_schema.innodb_metrics - WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; - -# Check the default value -SET @orig = @@global.innodb_purge_run_now; -SELECT @orig; - -# Stop of purge -SET GLOBAL innodb_purge_stop_now = ON; - -# Stop count should now be 1 -SELECT name, count - FROM information_schema.innodb_metrics - WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; - -SET GLOBAL innodb_purge_run_now = ON; - -# Should always be OFF -SELECT @@global.innodb_purge_run_now; - -# Both should be 1 now -SELECT name, count - FROM information_schema.innodb_metrics - WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; - ---disable_query_log -set global innodb_monitor_disable = all; -set global innodb_monitor_reset_all = all; - --- disable_warnings -set global innodb_monitor_enable = default; -set global innodb_monitor_disable = default; -set global innodb_monitor_reset = default; -set global innodb_monitor_reset_all = default; --- enable_warnings diff --git a/mysql-test/suite/sys_vars/t/innodb_purge_stop_now_basic.test b/mysql-test/suite/sys_vars/t/innodb_purge_stop_now_basic.test deleted file mode 100644 index 0704784dbcc..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_purge_stop_now_basic.test +++ /dev/null @@ -1,53 +0,0 @@ -# -# Basic test for innodb_purge_run_now, note it is a duplicate of -# innodb_purge_stop_now. -# - --- source include/have_innodb.inc - -# The config variable is a debug variable for now --- source include/have_debug.inc - ---disable_query_log -# Enable metrics for the counters we are going to use -set global innodb_monitor_enable = purge_stop_count; -set global innodb_monitor_enable = purge_resume_count; ---enable_query_log - -# Should be 0 for both -SELECT name, count - FROM information_schema.innodb_metrics - WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; - -# Check the default value -SET @orig = @@global.innodb_purge_run_now; -SELECT @orig; - -# Stop of purge -SET GLOBAL innodb_purge_stop_now = ON; - -# Stop count should now be 1 -SELECT name, count - FROM information_schema.innodb_metrics - WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; - -SET GLOBAL innodb_purge_run_now = ON; - -# Should always be OFF -SELECT @@global.innodb_purge_run_now; - -# Both should be 1 now -SELECT name, count - FROM information_schema.innodb_metrics - WHERE name = 'purge_stop_count' OR name = 'purge_resume_count'; - ---disable_query_log -set global innodb_monitor_disable = all; -set global innodb_monitor_reset_all = all; - --- disable_warnings -set global innodb_monitor_enable = default; -set global innodb_monitor_disable = default; -set global innodb_monitor_reset = default; -set global innodb_monitor_reset_all = default; --- enable_warnings diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6be10d77edf..fe931ce2616 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19750,8 +19750,6 @@ innobase_fts_find_ranking(FT_INFO* fts_hdl, uchar*, uint) #ifdef UNIV_DEBUG static my_bool innodb_background_drop_list_empty = TRUE; -static my_bool innodb_purge_run_now = TRUE; -static my_bool innodb_purge_stop_now = TRUE; static my_bool innodb_log_checkpoint_now = TRUE; static my_bool innodb_buf_flush_list_now = TRUE; static uint innodb_merge_threshold_set_all_debug @@ -19775,52 +19773,6 @@ wait_background_drop_list_empty( row_wait_for_background_drop_list_empty(); } -/****************************************************************//** -Set the purge state to RUN. If purge is disabled then it -is a no-op. This function is registered as a callback with MySQL. */ -static -void -purge_run_now_set( -/*==============*/ - THD* thd /*!< in: thread handle */ - MY_ATTRIBUTE((unused)), - struct st_mysql_sys_var* var /*!< in: pointer to system - variable */ - MY_ATTRIBUTE((unused)), - void* var_ptr /*!< out: where the formal - string goes */ - MY_ATTRIBUTE((unused)), - const void* save) /*!< in: immediate result from - check function */ -{ - if (*(my_bool*) save && trx_purge_state() != PURGE_STATE_DISABLED) { - trx_purge_run(); - } -} - -/****************************************************************//** -Set the purge state to STOP. If purge is disabled then it -is a no-op. This function is registered as a callback with MySQL. */ -static -void -purge_stop_now_set( -/*===============*/ - THD* thd /*!< in: thread handle */ - MY_ATTRIBUTE((unused)), - struct st_mysql_sys_var* var /*!< in: pointer to system - variable */ - MY_ATTRIBUTE((unused)), - void* var_ptr /*!< out: where the formal - string goes */ - MY_ATTRIBUTE((unused)), - const void* save) /*!< in: immediate result from - check function */ -{ - if (*(my_bool*) save && trx_purge_state() != PURGE_STATE_DISABLED) { - trx_purge_stop(); - } -} - /****************************************************************//** Force innodb to checkpoint. */ static @@ -20629,16 +20581,6 @@ static MYSQL_SYSVAR_BOOL(background_drop_list_empty, "Wait for the background drop list to become empty", NULL, wait_background_drop_list_empty, FALSE); -static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now, - PLUGIN_VAR_OPCMDARG, - "Set purge state to RUN", - NULL, purge_run_now_set, FALSE); - -static MYSQL_SYSVAR_BOOL(purge_stop_now, innodb_purge_stop_now, - PLUGIN_VAR_OPCMDARG, - "Set purge state to STOP", - NULL, purge_stop_now_set, FALSE); - static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now, PLUGIN_VAR_OPCMDARG, "Force checkpoint now", @@ -21912,8 +21854,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(purge_batch_size), #ifdef UNIV_DEBUG MYSQL_SYSVAR(background_drop_list_empty), - MYSQL_SYSVAR(purge_run_now), - MYSQL_SYSVAR(purge_stop_now), MYSQL_SYSVAR(log_checkpoint_now), MYSQL_SYSVAR(buf_flush_list_now), MYSQL_SYSVAR(merge_threshold_set_all_debug), From f5a833c3e085524585d1ae5b8303c168f075dab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Sep 2017 15:41:04 +0300 Subject: [PATCH 6/9] Clean up the logging of virtual column values in table-rebuilding online ALTER In online table-rebuilding ALTER TABLE (LOCK=NONE), virtual column values are being written to the online_log. WL#8149 in MySQL 5.7 changed some low-level functions that are also being used outside row0log.cc, causing performance penalty to other code. We revert those changes, and introduce separate functions for writing the virtual column values. The only functional change should be the one that is mentioned in MDEV-13795: row_log_table_low_redundant() will no longer write virtual column values along with old_pk, just like row_log_table_low(). As noted in MDEV-13795, some forms of table-rebuilding ALTER with virtual columns is broken. At least DROP PRIMARY KEY, ADD PRIMARY KEY is broken. rec_get_converted_size_temp(), rec_convert_dtuple_to_temp(): Remove the parameter for passing virtual column values. rec_get_converted_size_temp_v(), rec_convert_dtuple_to_temp_v(): New functions for appending virtual column values to the online_log. rec_get_converted_size_comp_prefix_low(), rec_convert_dtuple_to_rec_comp(): Remove the v_entry parameter, and do not allow n_fields=0. --- storage/innobase/include/rem0rec.h | 50 ++++++--- storage/innobase/rem/rem0rec.cc | 157 +++++++++++++++-------------- storage/innobase/row/row0log.cc | 62 ++++++------ storage/innobase/row/row0merge.cc | 6 +- 4 files changed, 147 insertions(+), 128 deletions(-) diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index a5e3268b7d7..61220d4f533 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -777,19 +777,42 @@ rec_copy( const rec_t* rec, const ulint* offsets); -/**********************************************************//** -Determines the size of a data tuple prefix in a temporary file. -@return total size */ +/** Determine the size of a data tuple prefix in a temporary file. +@param[in] index clustered or secondary index +@param[in] fields data fields +@param[in] n_fields number of data fields +@param[out] extra record header size +@return total size, in bytes */ ulint rec_get_converted_size_temp( -/*========================*/ - const dict_index_t* index, /*!< in: record descriptor */ - const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields,/*!< in: number of data fields */ - const dtuple_t* v_entry,/*!< in: dtuple contains virtual column - data */ - ulint* extra) /*!< out: extra size */ - MY_ATTRIBUTE((warn_unused_result)); + const dict_index_t* index, + const dfield_t* fields, + ulint n_fields, + ulint* extra) + MY_ATTRIBUTE((warn_unused_result, nonnull(1,2))); + +/** Determine the converted size of virtual column data in a temporary file. +@see rec_convert_dtuple_to_temp_v() +@param[in] index clustered index +@param[in] v clustered index record augmented with the values + of virtual columns +@return size in bytes */ +ulint +rec_get_converted_size_temp_v(const dict_index_t* index, const dtuple_t* v) + MY_ATTRIBUTE((warn_unused_result, nonnull)); + +/** Write indexed virtual column data into a temporary file. +@see rec_get_converted_size_temp_v() +@param[out] rec serialized record +@param[in] index clustered index +@param[in] v_entry clustered index record augmented with the values + of virtual columns */ +void +rec_convert_dtuple_to_temp_v( + byte* rec, + const dict_index_t* index, + const dtuple_t* v_entry) + MY_ATTRIBUTE((nonnull)); /******************************************************//** Determine the offset to each field in temporary file. @@ -812,10 +835,7 @@ rec_convert_dtuple_to_temp( rec_t* rec, /*!< out: record */ const dict_index_t* index, /*!< in: record descriptor */ const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields, /*!< in: number of fields */ - const dtuple_t* v_entry); /*!< in: dtuple contains - virtual column data */ - + ulint n_fields); /*!< in: number of fields */ /**************************************************************//** Copies the first n fields of a physical record to a new physical record in diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 4ad4730f37d..66e8ccec178 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -786,8 +786,6 @@ rec_get_converted_size_comp_prefix_low( it does not */ const dfield_t* fields, /*!< in: array of data fields */ ulint n_fields,/*!< in: number of data fields */ - const dtuple_t* v_entry,/*!< in: dtuple contains virtual column - data */ ulint* extra, /*!< out: extra size */ bool temp) /*!< in: whether this is a temporary file record */ @@ -795,20 +793,15 @@ rec_get_converted_size_comp_prefix_low( ulint extra_size; ulint data_size; ulint i; - ulint n_null = (n_fields > 0) ? index->n_nullable : 0; - ulint n_v_fields; + ut_ad(n_fields > 0); ut_ad(n_fields <= dict_index_get_n_fields(index)); ut_ad(!temp || extra); - /* At the time being, only temp file record could possible - store virtual columns */ - ut_ad(!v_entry || (dict_index_is_clust(index) && temp)); - n_v_fields = v_entry ? dtuple_get_n_v_fields(v_entry) : 0; + ut_d(ulint n_null = index->n_nullable); extra_size = temp - ? UT_BITS_IN_BYTES(n_null) - : REC_N_NEW_EXTRA_BYTES - + UT_BITS_IN_BYTES(n_null); + ? UT_BITS_IN_BYTES(index->n_nullable) + : REC_N_NEW_EXTRA_BYTES + UT_BITS_IN_BYTES(index->n_nullable); data_size = 0; if (temp && dict_table_is_comp(index->table)) { @@ -910,42 +903,50 @@ rec_get_converted_size_comp_prefix_low( *extra = extra_size; } - /* Log virtual columns */ - if (n_v_fields != 0) { - /* length marker */ - data_size += 2; + return(extra_size + data_size); +} - for (i = 0; i < n_v_fields; i++) { - dfield_t* vfield; - ulint flen; +/** Determine the converted size of virtual column data in a temporary file. +@see rec_convert_dtuple_to_temp_v() +@param[in] index clustered index +@param[in] v clustered index record augmented with the values + of virtual columns +@return size in bytes */ +ulint +rec_get_converted_size_temp_v(const dict_index_t* index, const dtuple_t* v) +{ + ut_ad(dict_index_is_clust(index)); - const dict_v_col_t* col - = dict_table_get_nth_v_col(index->table, i); + /* length marker */ + ulint data_size = 2; + const ulint n_v_fields = dtuple_get_n_v_fields(v); - /* Only those indexed needs to be logged */ - if (col->m_col.ord_part) { - data_size += mach_get_compressed_size( - i + REC_MAX_N_FIELDS); - vfield = dtuple_get_nth_v_field( - v_entry, col->v_pos); + for (ulint i = 0; i < n_v_fields; i++) { + const dict_v_col_t* col + = dict_table_get_nth_v_col(index->table, i); - flen = vfield->len; - - if (flen != UNIV_SQL_NULL) { - flen = ut_min( - flen, - static_cast( - DICT_MAX_FIELD_LEN_BY_FORMAT( - index->table))); - data_size += flen; - } - - data_size += mach_get_compressed_size(flen); - } + /* Only those indexed needs to be logged */ + if (!col->m_col.ord_part) { + continue; } + + data_size += mach_get_compressed_size(i + REC_MAX_N_FIELDS); + const dfield_t* vfield = dtuple_get_nth_v_field(v, col->v_pos); + ulint flen = vfield->len; + + if (flen != UNIV_SQL_NULL) { + flen = ut_min( + flen, + static_cast( + DICT_MAX_FIELD_LEN_BY_FORMAT( + index->table))); + data_size += flen; + } + + data_size += mach_get_compressed_size(flen); } - return(extra_size + data_size); + return(data_size); } /**********************************************************//** @@ -961,7 +962,7 @@ rec_get_converted_size_comp_prefix( { ut_ad(dict_table_is_comp(index->table)); return(rec_get_converted_size_comp_prefix_low( - index, fields, n_fields, NULL, extra, false)); + index, fields, n_fields, extra, false)); } /**********************************************************//** @@ -1007,7 +1008,7 @@ rec_get_converted_size_comp( } return(size + rec_get_converted_size_comp_prefix_low( - index, fields, n_fields, NULL, extra, false)); + index, fields, n_fields, extra, false)); } /***********************************************************//** @@ -1190,8 +1191,6 @@ rec_convert_dtuple_to_rec_comp( const dict_index_t* index, /*!< in: record descriptor */ const dfield_t* fields, /*!< in: array of data fields */ ulint n_fields,/*!< in: number of data fields */ - const dtuple_t* v_entry,/*!< in: dtuple contains - virtual column data */ ulint status, /*!< in: status bits of the record */ bool temp) /*!< in: whether to use the format for temporary files in @@ -1207,10 +1206,11 @@ rec_convert_dtuple_to_rec_comp( ulint n_node_ptr_field; ulint fixed_len; ulint null_mask = 1; - ulint n_null; - ulint num_v = v_entry ? dtuple_get_n_v_fields(v_entry) : 0; + ut_ad(n_fields > 0); ut_ad(temp || dict_table_is_comp(index->table)); + ulint n_null = index->n_nullable; + const ulint n_null_bytes = UT_BITS_IN_BYTES(n_null); if (temp) { ut_ad(status == REC_STATUS_ORDINARY); @@ -1223,8 +1223,6 @@ rec_convert_dtuple_to_rec_comp( temp = false; } } else { - ut_ad(v_entry == NULL); - ut_ad(num_v == 0); nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { @@ -1250,13 +1248,9 @@ rec_convert_dtuple_to_rec_comp( } end = rec; - - if (n_fields != 0) { - n_null = index->n_nullable; - lens = nulls - UT_BITS_IN_BYTES(n_null); - /* clear the SQL-null flags */ - memset(lens + 1, 0, nulls - lens); - } + /* clear the SQL-null flags */ + lens = nulls - n_null_bytes; + memset(lens + 1, 0, nulls - lens); /* Store the data and the offsets */ @@ -1351,13 +1345,25 @@ rec_convert_dtuple_to_rec_comp( end += len; } } +} - if (!num_v) { - return; - } +/** Write indexed virtual column data into a temporary file. +@see rec_get_converted_size_temp_v() +@param[out] rec serialized record +@param[in] index clustered index +@param[in] v_entry clustered index record augmented with the values + of virtual columns */ +void +rec_convert_dtuple_to_temp_v( + byte* rec, + const dict_index_t* index, + const dtuple_t* v_entry) +{ + ut_ad(dict_index_is_clust(index)); + const ulint num_v = dtuple_get_n_v_fields(v_entry); /* reserve 2 bytes for writing length */ - byte* ptr = end; + byte* ptr = rec; ptr += 2; /* Now log information on indexed virtual columns */ @@ -1400,7 +1406,7 @@ rec_convert_dtuple_to_rec_comp( } } - mach_write_to_2(end, ptr - end); + mach_write_to_2(rec, ptr - rec); } /*********************************************************//** @@ -1426,8 +1432,7 @@ rec_convert_dtuple_to_rec_new( rec = buf + extra_size; rec_convert_dtuple_to_rec_comp( - rec, index, dtuple->fields, dtuple->n_fields, NULL, - status, false); + rec, index, dtuple->fields, dtuple->n_fields, status, false); /* Set the info bits of the record */ rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple)); @@ -1490,21 +1495,21 @@ rec_convert_dtuple_to_rec( return(rec); } -/**********************************************************//** -Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT. -@return total size */ +/** Determine the size of a data tuple prefix in a temporary file. +@param[in] index clustered or secondary index +@param[in] fields data fields +@param[in] n_fields number of data fields +@param[out] extra record header size +@return total size, in bytes */ ulint rec_get_converted_size_temp( -/*========================*/ - const dict_index_t* index, /*!< in: record descriptor */ - const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields,/*!< in: number of data fields */ - const dtuple_t* v_entry,/*!< in: dtuple contains virtual column - data */ - ulint* extra) /*!< out: extra size */ + const dict_index_t* index, + const dfield_t* fields, + ulint n_fields, + ulint* extra) { return(rec_get_converted_size_comp_prefix_low( - index, fields, n_fields, v_entry, extra, true)); + index, fields, n_fields, extra, true)); } /******************************************************//** @@ -1530,11 +1535,9 @@ rec_convert_dtuple_to_temp( rec_t* rec, /*!< out: record */ const dict_index_t* index, /*!< in: record descriptor */ const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields, /*!< in: number of fields */ - const dtuple_t* v_entry) /*!< in: dtuple contains - virtual column data */ + ulint n_fields) /*!< in: number of fields */ { - rec_convert_dtuple_to_rec_comp(rec, index, fields, n_fields, v_entry, + rec_convert_dtuple_to_rec_comp(rec, index, fields, n_fields, REC_STATUS_ORDINARY, true); } diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 31a5402dc15..9e946757df3 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -302,7 +302,7 @@ row_log_online_op( extra_size+1 (and reserve 0 as the end-of-chunk marker). */ size = rec_get_converted_size_temp( - index, tuple->fields, tuple->n_fields, NULL, &extra_size); + index, tuple->fields, tuple->n_fields, &extra_size); ut_ad(size >= extra_size); ut_ad(size <= sizeof log->tail.buf); @@ -350,7 +350,7 @@ row_log_online_op( } rec_convert_dtuple_to_temp( - b + extra_size, index, tuple->fields, tuple->n_fields, NULL); + b + extra_size, index, tuple->fields, tuple->n_fields); b += size; if (mrec_size >= avail_size) { @@ -641,7 +641,7 @@ row_log_table_delete( ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field( old_pk, old_pk->n_fields - 1)->len); old_pk_size = rec_get_converted_size_temp( - new_index, old_pk->fields, old_pk->n_fields, NULL, + new_index, old_pk->fields, old_pk->n_fields, &old_pk_extra_size); ut_ad(old_pk_extra_size < 0x100); @@ -671,9 +671,7 @@ row_log_table_delete( /* Check if we need to log virtual column data */ if (ventry->n_v_fields > 0) { - ulint v_extra; - mrec_size += rec_get_converted_size_temp( - new_index, NULL, 0, ventry, &v_extra); + mrec_size += rec_get_converted_size_temp_v(new_index, ventry); } if (byte* b = row_log_table_open(index->online_log, @@ -687,7 +685,7 @@ row_log_table_delete( rec_convert_dtuple_to_temp( b + old_pk_extra_size, new_index, - old_pk->fields, old_pk->n_fields, NULL); + old_pk->fields, old_pk->n_fields); b += old_pk_size; @@ -720,8 +718,7 @@ row_log_table_delete( /* log virtual columns */ if (ventry->n_v_fields > 0) { - rec_convert_dtuple_to_temp( - b, new_index, NULL, 0, ventry); + rec_convert_dtuple_to_temp_v(b, new_index, ventry); b += mach_read_from_2(b); } @@ -812,15 +809,16 @@ row_log_table_low_redundant( } size = rec_get_converted_size_temp( - index, tuple->fields, tuple->n_fields, ventry, &extra_size); + index, tuple->fields, tuple->n_fields, &extra_size); + ulint v_size = ventry + ? rec_get_converted_size_temp_v(index, ventry) : 0; - mrec_size = ROW_LOG_HEADER_SIZE + size + (extra_size >= 0x80); + mrec_size = ROW_LOG_HEADER_SIZE + size + v_size + (extra_size >= 0x80); if (num_v) { if (o_ventry) { - ulint v_extra = 0; - mrec_size += rec_get_converted_size_temp( - index, NULL, 0, o_ventry, &v_extra); + mrec_size += rec_get_converted_size_temp_v( + index, o_ventry); } } else if (index->table->n_v_cols) { mrec_size += 2; @@ -839,7 +837,7 @@ row_log_table_low_redundant( old_pk_size = rec_get_converted_size_temp( new_index, old_pk->fields, old_pk->n_fields, - ventry, &old_pk_extra_size); + &old_pk_extra_size); ut_ad(old_pk_extra_size < 0x100); mrec_size += 1/*old_pk_extra_size*/ + old_pk_size; } @@ -853,8 +851,7 @@ row_log_table_low_redundant( rec_convert_dtuple_to_temp( b + old_pk_extra_size, new_index, - old_pk->fields, old_pk->n_fields, - ventry); + old_pk->fields, old_pk->n_fields); b += old_pk_size; } @@ -867,14 +864,17 @@ row_log_table_low_redundant( } rec_convert_dtuple_to_temp( - b + extra_size, index, tuple->fields, tuple->n_fields, - ventry); + b + extra_size, index, tuple->fields, tuple->n_fields); b += size; + if (ventry) { + rec_convert_dtuple_to_temp_v(b, new_index, ventry); + b += v_size; + } if (num_v) { if (o_ventry) { - rec_convert_dtuple_to_temp( - b, new_index, NULL, 0, o_ventry); + rec_convert_dtuple_to_temp_v( + b, new_index, o_ventry); b += mach_read_from_2(b); } } else if (index->table->n_v_cols) { @@ -964,13 +964,11 @@ row_log_table_low( + (extra_size >= 0x80) + rec_offs_size(offsets) - omit_size; if (ventry && ventry->n_v_fields > 0) { - ulint v_extra = 0; - mrec_size += rec_get_converted_size_temp( - new_index, NULL, 0, ventry, &v_extra); + mrec_size += rec_get_converted_size_temp_v(new_index, ventry); if (o_ventry) { - mrec_size += rec_get_converted_size_temp( - new_index, NULL, 0, o_ventry, &v_extra); + mrec_size += rec_get_converted_size_temp_v( + new_index, o_ventry); } } else if (index->table->n_v_cols) { /* Always leave 2 bytes length marker for virtual column @@ -992,7 +990,7 @@ row_log_table_low( old_pk_size = rec_get_converted_size_temp( new_index, old_pk->fields, old_pk->n_fields, - NULL, &old_pk_extra_size); + &old_pk_extra_size); ut_ad(old_pk_extra_size < 0x100); mrec_size += 1/*old_pk_extra_size*/ + old_pk_size; } @@ -1006,8 +1004,7 @@ row_log_table_low( rec_convert_dtuple_to_temp( b + old_pk_extra_size, new_index, - old_pk->fields, old_pk->n_fields, - NULL); + old_pk->fields, old_pk->n_fields); b += old_pk_size; } @@ -1025,13 +1022,12 @@ row_log_table_low( b += rec_offs_data_size(offsets); if (ventry && ventry->n_v_fields > 0) { - rec_convert_dtuple_to_temp( - b, new_index, NULL, 0, ventry); + rec_convert_dtuple_to_temp_v(b, new_index, ventry); b += mach_read_from_2(b); if (o_ventry) { - rec_convert_dtuple_to_temp( - b, new_index, NULL, 0, o_ventry); + rec_convert_dtuple_to_temp_v( + b, new_index, o_ventry); b += mach_read_from_2(b); } } else if (index->table->n_v_cols) { diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index cba453ced24..85fac6c0bba 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -407,7 +407,7 @@ row_merge_buf_encode( ulint extra_size; size = rec_get_converted_size_temp( - index, entry->fields, n_fields, NULL, &extra_size); + index, entry->fields, n_fields, &extra_size); ut_ad(size >= extra_size); /* Encode extra_size + 1 */ @@ -420,7 +420,7 @@ row_merge_buf_encode( } rec_convert_dtuple_to_temp(*b + extra_size, index, - entry->fields, n_fields, NULL); + entry->fields, n_fields); *b += size; } @@ -893,7 +893,7 @@ row_merge_buf_add( ulint extra; size = rec_get_converted_size_temp( - index, entry->fields, n_fields, NULL, &extra); + index, entry->fields, n_fields, &extra); ut_ad(data_size + extra_size == size); ut_ad(extra_size == extra); From 88106ef3529ac908d9adf88242722752f11b59a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Sep 2017 07:52:32 +0300 Subject: [PATCH 7/9] Fix a warning for a debug assertion The type uint16_t is apparently promoted to int in a comparison, causing a sign mismatch when comparing to ulint. Convert both operands to uint16_t. --- storage/innobase/include/page0page.ic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index b464e497de1..db98f2e6558 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -731,7 +731,7 @@ page_dir_set_n_heap( ulint n_heap) /*!< in: number of records */ { ut_ad(n_heap < 0x8000); - ut_ad(!page_zip || n_heap + ut_ad(!page_zip || uint16_t(n_heap) == (page_header_get_field(page, PAGE_N_HEAP) & 0x7fff) + 1); page_header_set_field(page, page_zip, PAGE_N_HEAP, n_heap From 126a581b4585f707eb165aa250e58bbeada480d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Sep 2017 08:00:28 +0300 Subject: [PATCH 8/9] Fix warnings for page_header_get_field() comparisons The type uint16_t is apparently promoted to int in a comparison, causing a sign mismatch when comparing to ulint. Convert to ulint before comparison. --- storage/innobase/page/page0page.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 3765f8112a1..0a2f11ff3b0 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2117,7 +2117,7 @@ page_simple_validate_old( goto func_exit; } - if (UNIV_UNLIKELY(page_header_get_field(page, PAGE_N_RECS) + if (UNIV_UNLIKELY(ulint(page_header_get_field(page, PAGE_N_RECS)) + PAGE_HEAP_NO_USER_LOW != count + 1)) { ib::error() << "n recs wrong " @@ -2308,7 +2308,7 @@ page_simple_validate_new( goto func_exit; } - if (UNIV_UNLIKELY(page_header_get_field(page, PAGE_N_RECS) + if (UNIV_UNLIKELY(ulint(page_header_get_field(page, PAGE_N_RECS)) + PAGE_HEAP_NO_USER_LOW != count + 1)) { ib::error() << "n recs wrong " From cfd51c01e17cd2689764a6c47de1e218adf9aaec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Sep 2017 08:06:40 +0300 Subject: [PATCH 9/9] Fix one more warning for page_header_get_field() --- storage/innobase/page/page0page.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 0a2f11ff3b0..b2c27acfbaa 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2615,7 +2615,7 @@ n_owned_zero: goto func_exit; } - if (UNIV_UNLIKELY(page_header_get_field(page, PAGE_N_RECS) + if (UNIV_UNLIKELY(ulint(page_header_get_field(page, PAGE_N_RECS)) + PAGE_HEAP_NO_USER_LOW != count + 1)) { ib::error() << "n recs wrong "